Skip to content

fix(core): preserve JSON Schema enum case order#3028

Merged
schani merged 1 commit into
masterfrom
agent/fix-issue-1289
Jul 20, 2026
Merged

fix(core): preserve JSON Schema enum case order#3028
schani merged 1 commit into
masterfrom
agent/fix-issue-1289

Conversation

@schani

@schani schani commented Jul 20, 2026

Copy link
Copy Markdown
Member

Bug

C++ (and, as it turns out, every other language) emitted enum cases in
alphabetical order instead of the order they appear in the source JSON
Schema / JSON enum array.

Repro from the issue:

quicktype -l c++ --code-format with-getter-setter --wstring use-string --const-style west-const --type-style pascal-case --member-style camel-case --enumerator-style pascal-case --no-boost -s schema test.json

with schema property "enum": ["B", "A", "E"] produced:

enum class ErrorCode : int { A, B, E };

instead of preserving the declared order B, A, E.

Root cause

ConvenienceRenderer.forEachEnumCase (in
packages/quicktype-core/src/ConvenienceRenderer.ts) unconditionally
sorted enum case names alphabetically by their rendered Name before
handing them to a language renderer's emitEnum:

const sortedCaseNames = mapSortBy(caseNames, (n) =>
    defined(this.names.get(n)),
);
this.forEachWithBlankLines(sortedCaseNames, blankLocations, f);

forEachEnumCase is called by essentially every language's emitEnum
(C++, C#, Java, Kotlin, Swift, Python, Go, Rust, PHP, Ruby, etc.), so
this alphabetization was not C++-specific — it affected all generators.
The underlying caseNames map already reflects the original
schema/JSON input order (JS Map/Set preserve insertion order), so
the fix is simply to stop forcibly re-sorting it, mirroring how
forEachClassProperty already preserves declared property order by
default (only alphabetizing when the existing, opt-in
_alphabetizeProperties renderer option is set).

Fix

Removed the unconditional mapSortBy alphabetization in
forEachEnumCase, so enum cases are emitted in the same order they
appear in the source input.

Test coverage

  • Added test/unit/enum-order.test.ts, which reproduces the issue's
    exact schema (enum: ["B", "A", "E"]) and asserts the generated C++
    contains enum class ErrorCode : int { B, A, E };. This fails on
    unfixed code (previously emitted A, B, E) and passes after the fix.
  • End-to-end fixture coverage already exists via
    test/inputs/schema/enum.schema, whose enum arrays
    (["lawful", "neutral", "chaotic"], ["good", "neutral", "evil"])
    are non-alphabetical and are exercised for C++ through the
    schema-cplusplus fixture (not in that language's skipSchema list),
    giving ongoing round-trip regression coverage for this case.

Verification

  • npm run build passes.
  • npx vitest run test/unit — all 171 unit tests pass, including the
    new regression test.
  • QUICKTEST=true FIXTURE=schema-cplusplus script/test — all 70 tests
    pass locally (g++ toolchain available in this environment).
  • Manually re-ran the exact CLI repro from the issue; output now shows
    enum class ErrorCode : int { B, A, E };, matching input order.
  • CI will additionally validate the other language fixtures that call
    forEachEnumCase.

Fixes #1289.

🤖 Generated with Claude Code

ConvenienceRenderer.forEachEnumCase always alphabetized enum cases by
their rendered name before handing them to every language renderer's
emitEnum, so C++ (and other languages) generated enums in alphabetical
order instead of the order declared in the source JSON Schema/JSON.
Stop sorting and let the existing insertion order (already preserved
by the underlying case-names map) flow through unchanged.

Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
@schani
schani merged commit fd68cc8 into master Jul 20, 2026
28 checks passed
@schani
schani deleted the agent/fix-issue-1289 branch July 20, 2026 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

json scheme to Cpp, enum has no origin order

1 participant