fix(cpp): compile optional any-typed properties with --hide-null-optional#3054
Merged
Conversation
…onal (#1961) Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…ped values (#1961) The PR's updated optional-any.schema fixture added a required bar:boolean property with a .fail.json negative sample containing a string for bar. Without strict_types, PHP weakly coerces the string into a bool instead of throwing, so the generated PHP program didn't fail as the fixture expects. Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
…rder (#undefined) Merging master (which has moved substantially, including #1289 which stopped ConvenienceRenderer.forEachEnumCase from alphabetizing enum cases) into this branch surfaced a pre-existing, unrelated master-side unit test failure: test/unit/cjson-enum-default.test.ts still asserted the old alphabetical enum-case order, but cjson (like every other language) now preserves JSON Schema declaration order. Update the expected string to match; no renderer/core code changes. Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
…ed at runtime)
The PR's new optional-any.3.fail.json case (bar given as a string where the
schema requires boolean) relies on scalar-type validation during decode.
Elixir's generated from_map/1 does raw, unchecked field assignment, so it
already skips strict-optional.schema/required.schema/intersection.schema for
the same documented reason ("Struct keys cannot be enforced at runtime in
Elixir"). Add optional-any.schema to that same skip group.
Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
When generating C++ (nlohmann, either boost or
--no-boost) with--hide-null-optional, an optional property with no declared type("any", e.g. an empty
{}schema) produces ato_jsonguard that doesnot compile:
get_alpha()returnsconst nlohmann::json &.nlohmann::jsondeliberately has no
operator bool()(nlohmann/json#951), so this is acompile error.
Root cause
For every other type, an optional property is wrapped in
std::optional<T>/std::shared_ptr<T>, whoseoperator bool()makesif (x.get_foo())valid. Butany-typed properties are represented as aplain, unwrapped
nlohmann::jsonmember (seecppType()inCPlusPlusRenderer.ts, which forcesisOptional = falseforAnyType).The
to_jsonemitter's--hide-null-optionalguard(
packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts)didn't account for this and always emitted the
if (x.get_<name>())pattern for any optional property, regardless of whether the underlying
C++ type supports contextual bool conversion.
The fix
For optional properties whose type is
nullorany(i.e. backed by abare
nlohmann::jsonvalue, not anoptional/shared_ptrwrapper), the--hide-null-optionalguard now tests!value.is_null()instead ofrelying on an implicit bool conversion. This compiles correctly and
preserves the intended "omit the key when the value is absent/null"
behavior. All other optional property types are unaffected and keep the
existing
if (x.get_foo())guard.Test coverage
Extended the existing
test/inputs/schema/optional-any.schemaJSONSchema fixture with:
bar: booleanproperty alongside the existing optionaluntyped
fooproperty (updated.1.json/.2.jsonsamplesaccordingly),
.3.fail.jsonnegative sample (bargiven a non-boolean value,expected to fail),
quickTestRendererOptionsentry intest/languages.tspinninghide-null-optional: truefor this schema, so the C++ schema fixtureactually exercises
--hide-null-optionalagainst an any-typedproperty (previously nothing in the C++ fixture suite turned that
option on for this schema).
Verification
repro schema with
--lang c++ --hide-null-optional --no-boostandobserving the invalid
if (x.get_alpha())guard in the output.now
if (!x.get_alpha().is_null()), and other optional properties(e.g. an
int64_t) are unaffected.npm run buildpasses.QUICKTEST=true FIXTURE=schema-cplusplus script/test, compiling with g++): all 72tests pass, including the new
optional-any.schemacase withhide-null-optional: true.optional-any.schemais a shared fixture input used by manyother language schema fixtures, also ran
schema-pythonandschema-typescriptlocally to confirm the input change doesn'tregress other languages: both pass. CI will validate the remaining
languages that use this fixture.
Fixes #1961.
🤖 Generated with Claude Code