Commit a8e800bd authored by cryptocode's avatar cryptocode Committed by Wouter van Oortmerssen

Add --force-empty-vectors option (#5653)

The rationale for this option is that JSON clients typically want empty arrays (i.e [] in the JSON) instead of missing properties, but not empty strings when the value isn't set.
--force-empty is kept as-is, i.e. it will force both empty strings and vectors.

Closes #5652
parent d7530ae9
...@@ -203,5 +203,8 @@ Additional options: ...@@ -203,5 +203,8 @@ Additional options:
- `--force-empty` : When serializing from object API representation, force - `--force-empty` : When serializing from object API representation, force
strings and vectors to empty rather than null. strings and vectors to empty rather than null.
- `--force-empty-vectors` : When serializing from object API representation, force
vectors to empty rather than null.
NOTE: short-form options for generators are deprecated, use the long form NOTE: short-form options for generators are deprecated, use the long form
whenever possible. whenever possible.
...@@ -588,9 +588,13 @@ struct IDLOptions { ...@@ -588,9 +588,13 @@ struct IDLOptions {
// for code generation. // for code generation.
unsigned long lang_to_generate; unsigned long lang_to_generate;
// If set (default behavior), empty string and vector fields will be set to // If set (default behavior), empty string fields will be set to nullptr to make
// nullptr to make the flatbuffer more compact. // the flatbuffer more compact.
bool set_empty_to_null; bool set_empty_strings_to_null;
// If set (default behavior), empty vector fields will be set to nullptr to make
// the flatbuffer more compact.
bool set_empty_vectors_to_null;
IDLOptions() IDLOptions()
: use_flexbuffers(false), : use_flexbuffers(false),
...@@ -635,7 +639,8 @@ struct IDLOptions { ...@@ -635,7 +639,8 @@ struct IDLOptions {
lang(IDLOptions::kJava), lang(IDLOptions::kJava),
mini_reflect(IDLOptions::kNone), mini_reflect(IDLOptions::kNone),
lang_to_generate(0), lang_to_generate(0),
set_empty_to_null(true) {} set_empty_strings_to_null(true),
set_empty_vectors_to_null(true) {}
}; };
// This encapsulates where the parser is in the current source file. // This encapsulates where the parser is in the current source file.
......
...@@ -63,7 +63,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { ...@@ -63,7 +63,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
const Generator &g = params_.generators[i]; const Generator &g = params_.generators[i];
std::stringstream full_name; std::stringstream full_name;
full_name << std::setw(12) << std::left << g.generator_opt_long; full_name << std::setw(16) << std::left << g.generator_opt_long;
const char *name = g.generator_opt_short ? g.generator_opt_short : " "; const char *name = g.generator_opt_short ? g.generator_opt_short : " ";
const char *help = g.generator_help; const char *help = g.generator_help;
...@@ -101,7 +101,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { ...@@ -101,7 +101,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --gen-object-api Generate an additional object-based API.\n" " --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n" " --gen-compare Generate operator== for object-based API types.\n"
" --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n" " --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
" --java-checkerframework Add @Pure for Java.\n" " --java-checkerframe work Add @Pure for Java.\n"
" --gen-generated Add @Generated annotation for Java\n" " --gen-generated Add @Generated annotation for Java\n"
" --gen-all Generate not just code for the current schema files,\n" " --gen-all Generate not just code for the current schema files,\n"
" but for all files it includes as well.\n" " but for all files it includes as well.\n"
...@@ -149,6 +149,8 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { ...@@ -149,6 +149,8 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --force-defaults Emit default values in binary output from JSON\n" " --force-defaults Emit default values in binary output from JSON\n"
" --force-empty When serializing from object API representation,\n" " --force-empty When serializing from object API representation,\n"
" force strings and vectors to empty rather than null.\n" " force strings and vectors to empty rather than null.\n"
" --force-empty-vectors When serializing from object API representation,\n"
" force vectors to empty rather than null.\n"
" --flexbuffers Used with \"binary\" and \"json\" options, it generates\n" " --flexbuffers Used with \"binary\" and \"json\" options, it generates\n"
" data using schema-less FlexBuffers.\n" " data using schema-less FlexBuffers.\n"
"FILEs may be schemas (must end in .fbs), binary schemas (must end in .bfbs),\n" "FILEs may be schemas (must end in .fbs), binary schemas (must end in .bfbs),\n"
...@@ -323,7 +325,10 @@ int FlatCompiler::Compile(int argc, const char **argv) { ...@@ -323,7 +325,10 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--force-defaults") { } else if (arg == "--force-defaults") {
opts.force_defaults = true; opts.force_defaults = true;
} else if (arg == "--force-empty") { } else if (arg == "--force-empty") {
opts.set_empty_to_null = false; opts.set_empty_strings_to_null = false;
opts.set_empty_vectors_to_null = false;
} else if (arg == "--force-empty-vectors") {
opts.set_empty_vectors_to_null = false;
} else if (arg == "--java-primitive-has-method") { } else if (arg == "--java-primitive-has-method") {
opts.java_primitive_has_method = true; opts.java_primitive_has_method = true;
} else if (arg == "--flexbuffers") { } else if (arg == "--flexbuffers") {
......
...@@ -2452,10 +2452,10 @@ class CppGenerator : public BaseGenerator { ...@@ -2452,10 +2452,10 @@ class CppGenerator : public BaseGenerator {
// For optional fields, check to see if there actually is any data // For optional fields, check to see if there actually is any data
// in _o->field before attempting to access it. If there isn't, // in _o->field before attempting to access it. If there isn't,
// depending on set_empty_to_null either set it to 0 or an empty string. // depending on set_empty_strings_to_null either set it to 0 or an empty string.
if (!field.required) { if (!field.required) {
auto empty_value = auto empty_value =
opts.set_empty_to_null ? "0" : "_fbb.CreateSharedString(\"\")"; opts.set_empty_strings_to_null ? "0" : "_fbb.CreateSharedString(\"\")";
code = value + ".empty() ? " + empty_value + " : " + code; code = value + ".empty() ? " + empty_value + " : " + code;
} }
break; break;
...@@ -2557,10 +2557,10 @@ class CppGenerator : public BaseGenerator { ...@@ -2557,10 +2557,10 @@ class CppGenerator : public BaseGenerator {
} }
} }
// If set_empty_to_null option is enabled, for optional fields, check to // If set_empty_vectors_to_null option is enabled, for optional fields, check to
// see if there actually is any data in _o->field before attempting to // see if there actually is any data in _o->field before attempting to
// access it. // access it.
if (opts.set_empty_to_null && !field.required) { if (opts.set_empty_vectors_to_null && !field.required) {
code = value + ".size() ? " + code + " : 0"; code = value + ".size() ? " + code + " : 0";
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment