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:
- `--force-empty` : When serializing from object API representation, force
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
whenever possible.
......@@ -588,9 +588,13 @@ struct IDLOptions {
// for code generation.
unsigned long lang_to_generate;
// If set (default behavior), empty string and vector fields will be set to
// nullptr to make the flatbuffer more compact.
bool set_empty_to_null;
// If set (default behavior), empty string fields will be set to nullptr to make
// the flatbuffer more compact.
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()
: use_flexbuffers(false),
......@@ -635,7 +639,8 @@ struct IDLOptions {
lang(IDLOptions::kJava),
mini_reflect(IDLOptions::kNone),
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.
......
......@@ -63,7 +63,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
const Generator &g = params_.generators[i];
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 *help = g.generator_help;
......@@ -71,86 +71,88 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
}
// clang-format off
ss <<
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n"
" --version Print the version number of flatc and exit.\n"
" --strict-json Strict JSON: field names must be / will be quoted,\n"
" no trailing commas in tables/vectors.\n"
" --allow-non-utf8 Pass non-UTF-8 input through parser and emit nonstandard\n"
" \\x escapes in JSON. (Default is to raise parse error on\n"
" non-UTF-8 input.)\n"
" --natural-utf8 Output strings with UTF-8 as human-readable strings.\n"
" By default, UTF-8 characters are printed as \\uXXXX escapes.\n"
" --defaults-json Output fields whose value is the default when\n"
" writing JSON\n"
" --unknown-json Allow fields in JSON that are not defined in the\n"
" schema. These fields will be discared when generating\n"
" binaries.\n"
" --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
" --scoped-enums Use C++11 style scoped and strongly typed enums.\n"
" also implies --no-prefix.\n"
" --gen-includes (deprecated), this is the default behavior.\n"
" If the original behavior is required (no include\n"
" statements) use --no-includes.\n"
" --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++ / Python).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C# and Go.\n"
" --gen-name-strings Generate type name functions for C++.\n"
" --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n"
" --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
" --java-checkerframework Add @Pure for Java.\n"
" --gen-generated Add @Generated annotation for Java\n"
" --gen-all Generate not just code for the current schema files,\n"
" but for all files it includes as well.\n"
" If the language uses a single file for output (by default\n"
" the case for C++ and JS), all code will end up in this one\n"
" file.\n"
" --cpp-include Adds an #include in generated file.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr).\n"
" --cpp-str-type T Set object API string type (default std::string).\n"
" T::c_str(), T::length() and T::empty() must be supported.\n"
" The custom type also needs to be constructible from std::string\n"
" (see the --cpp-str-flex-ctor option to change this behavior).\n"
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
" from Flatbuffers, but (char* + length).\n"
" --object-prefix Customise class prefix for C++ object-based API.\n"
" --object-suffix Customise class suffix for C++ object-based API.\n"
" Default value is \"T\".\n"
" --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --es6-js-export Uses ECMAScript 6 export style lines in JS.\n"
" --go-namespace Generate the overrided namespace in Golang.\n"
" --go-import Generate the overrided import for flatbuffers in Golang\n"
" (default is \"github.com/google/flatbuffers/go\").\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --size-prefixed Input binaries are size prefixed buffers.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --oneof-union Translate .proto oneofs to flatbuffer unions.\n"
" --grpc Generate GRPC interfaces for the specified languages.\n"
" --schema Serialize schemas instead of JSON (use with -b).\n"
" --bfbs-comments Add doc comments to the binary schema files.\n"
" --bfbs-builtins Add builtin attributes to the binary schema files.\n"
" --conform FILE Specify a schema the following schemas should be\n"
" an evolution of. Gives errors if not.\n"
" --conform-includes Include path for the schema given with --conform PATH\n"
" --include-prefix Prefix this path to any generated include statements.\n"
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n"
" --version Print the version number of flatc and exit.\n"
" --strict-json Strict JSON: field names must be / will be quoted,\n"
" no trailing commas in tables/vectors.\n"
" --allow-non-utf8 Pass non-UTF-8 input through parser and emit nonstandard\n"
" \\x escapes in JSON. (Default is to raise parse error on\n"
" non-UTF-8 input.)\n"
" --natural-utf8 Output strings with UTF-8 as human-readable strings.\n"
" By default, UTF-8 characters are printed as \\uXXXX escapes.\n"
" --defaults-json Output fields whose value is the default when\n"
" writing JSON\n"
" --unknown-json Allow fields in JSON that are not defined in the\n"
" schema. These fields will be discared when generating\n"
" binaries.\n"
" --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
" --scoped-enums Use C++11 style scoped and strongly typed enums.\n"
" also implies --no-prefix.\n"
" --gen-includes (deprecated), this is the default behavior.\n"
" If the original behavior is required (no include\n"
" statements) use --no-includes.\n"
" --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++ / Python).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C# and Go.\n"
" --gen-name-strings Generate type name functions for C++.\n"
" --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n"
" --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
" --java-checkerframe work Add @Pure for Java.\n"
" --gen-generated Add @Generated annotation for Java\n"
" --gen-all Generate not just code for the current schema files,\n"
" but for all files it includes as well.\n"
" If the language uses a single file for output (by default\n"
" the case for C++ and JS), all code will end up in this one\n"
" file.\n"
" --cpp-include Adds an #include in generated file.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr).\n"
" --cpp-str-type T Set object API string type (default std::string).\n"
" T::c_str(), T::length() and T::empty() must be supported.\n"
" The custom type also needs to be constructible from std::string\n"
" (see the --cpp-str-flex-ctor option to change this behavior).\n"
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
" from Flatbuffers, but (char* + length).\n"
" --object-prefix Customise class prefix for C++ object-based API.\n"
" --object-suffix Customise class suffix for C++ object-based API.\n"
" Default value is \"T\".\n"
" --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --es6-js-export Uses ECMAScript 6 export style lines in JS.\n"
" --go-namespace Generate the overrided namespace in Golang.\n"
" --go-import Generate the overrided import for flatbuffers in Golang\n"
" (default is \"github.com/google/flatbuffers/go\").\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --size-prefixed Input binaries are size prefixed buffers.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --oneof-union Translate .proto oneofs to flatbuffer unions.\n"
" --grpc Generate GRPC interfaces for the specified languages.\n"
" --schema Serialize schemas instead of JSON (use with -b).\n"
" --bfbs-comments Add doc comments to the binary schema files.\n"
" --bfbs-builtins Add builtin attributes to the binary schema files.\n"
" --conform FILE Specify a schema the following schemas should be\n"
" an evolution of. Gives errors if not.\n"
" --conform-includes Include path for the schema given with --conform PATH\n"
" --include-prefix Prefix this path to any generated include statements.\n"
" PATH\n"
" --keep-prefix Keep original prefix of schema include statement.\n"
" --no-fb-import Don't include flatbuffers import statement for TypeScript.\n"
" --no-ts-reexport Don't re-export imported dependencies for TypeScript.\n"
" --short-names Use short function names for JS and TypeScript.\n"
" --reflect-types Add minimal type reflection to code generation.\n"
" --reflect-names Add minimal type/name reflection.\n"
" --root-type T Select or override the default root_type\n"
" --force-defaults Emit default values in binary output from JSON\n"
" --force-empty When serializing from object API representation,\n"
" force strings and vectors to empty rather than null.\n"
" --flexbuffers Used with \"binary\" and \"json\" options, it generates\n"
" data using schema-less FlexBuffers.\n"
" --keep-prefix Keep original prefix of schema include statement.\n"
" --no-fb-import Don't include flatbuffers import statement for TypeScript.\n"
" --no-ts-reexport Don't re-export imported dependencies for TypeScript.\n"
" --short-names Use short function names for JS and TypeScript.\n"
" --reflect-types Add minimal type reflection to code generation.\n"
" --reflect-names Add minimal type/name reflection.\n"
" --root-type T Select or override the default root_type\n"
" --force-defaults Emit default values in binary output from JSON\n"
" --force-empty When serializing from object API representation,\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"
" data using schema-less FlexBuffers.\n"
"FILEs may be schemas (must end in .fbs), binary schemas (must end in .bfbs),\n"
"or JSON files (conforming to preceding schema). FILEs after the -- must be\n"
"binary flatbuffer format files.\n"
......@@ -323,7 +325,10 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--force-defaults") {
opts.force_defaults = true;
} 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") {
opts.java_primitive_has_method = true;
} else if (arg == "--flexbuffers") {
......
......@@ -2452,10 +2452,10 @@ class CppGenerator : public BaseGenerator {
// For optional fields, check to see if there actually is any data
// 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) {
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;
}
break;
......@@ -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
// access it.
if (opts.set_empty_to_null && !field.required) {
if (opts.set_empty_vectors_to_null && !field.required) {
code = value + ".size() ? " + code + " : 0";
}
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