Skip to content

Use JSON instead of YAML for typespec-python code model serialization#11178

Draft
timotheeguerin wants to merge 3 commits into
mainfrom
python-json-codemodel
Draft

Use JSON instead of YAML for typespec-python code model serialization#11178
timotheeguerin wants to merge 3 commits into
mainfrom
python-json-codemodel

Conversation

@timotheeguerin

@timotheeguerin timotheeguerin commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Switches the code model interchange format between the emitter and the Python generator in @typespec/http-client-python from YAML to a reference-preserving JSON format.

To stay consistent with the C# emitter, this uses the same $id/$ref convention (System.Text.Json's ReferenceHandler.Preserve):

  • The first time an object is seen: { "$id": "N", ...properties }
  • The first time an array is seen: { "$id": "N", "$values": [...] }
  • Any later reference to an already-seen node: { "$ref": "N" }

The code model is a cyclic / shared object graph (on the Azure network spec: 35,175 objects and 32,075 arrays, of which 3,739 objects and 2,855 arrays are shared, plus 1,022 cycle back-edges). Because $id is registered before recursing into a node's children, cycles are encoded as a $ref back to the enclosing node — so cycles are preserved (the C# writer drops them, which the Python model can't tolerate). The Python decoder reconstructs a graph with identical shared identity and cycles, so the generator's model layer needs zero changes.

Changes

  • New: emitter/src/code-model-serializer.ts — the $id/$ref serializer (cycle-safe).
  • New: generator/pygen/_codemodel_json.py — matching Python loads/dumps decoder/encoder.
  • Removes the js-yaml/@types/js-yaml (emitter) and PyYAML/types-PyYAML (generator) dependencies.
  • Renames the emit-yaml-only emitter option to emit-codemodel-only.
  • Updates CI regenerate scripts, batch runner, mypy config, and ARCHITECTURE.md.

Performance

Benchmarked on the Azure network spec (large real-world spec):

Stage YAML (js-yaml / PyYAML) JSON ($id/$ref)
JS serialize ~1000 ms ~60 ms
Python load ~11000 ms ~50 ms
Python dump ~5500 ms ~40 ms
File size 14.4 MB 8.8 MB

End-to-end serialization: ~29 s → ~0.2 s.

Note: a faster JS YAML library (yaml/eemeli) was evaluated and is worse — ~1.8× slower to serialize and ~70× slower to parse than js-yaml, and it rejects the model by default (alias-count guard). The bottleneck was the pure-Python PyYAML side under Pyodide, which only JSON fixes.

Validation

  • Full package build (emitter + pygen wheel) ✅
  • End-to-end: compiled the network spec → $id/$ref code model → generator produced 31 correct .py files ✅
  • Python codec reconstructs the identical graph (all structural metrics match) and round-trips stably ✅
  • Generator unit tests, lint (10/10), format, and mypy all pass ✅

…ialization

Switch the emitter<->generator code model interchange format from YAML to a
graph-preserving JSON codec (flatted). The code model is a cyclic/shared object
graph, so a plain JSON format is insufficient; the flatted codec preserves
cycles and shared references while being far faster than YAML.

- Add pygen/_codemodel_json.py (Python port of the flatted format)
- Remove js-yaml (emitter) and PyYAML (generator) dependencies
- Rename the emit-yaml-only option to emit-codemodel-only

On the Azure network spec, end-to-end serialization drops from ~29s to ~0.2s
and the code model file shrinks from 14.4MB to 6.5MB.
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:python Issue for the Python client emitter: @typespec/http-client-python label Jul 6, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jul 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-python@11178

commit: 30af72e

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/http-client-python
Show changes

@typespec/http-client-python - internal ✏️

Switch the code model interchange format between the emitter and the Python generator from YAML to a reference-preserving JSON format, using the same $id/$ref convention as the C# emitter (System.Text.Json ReferenceHandler.Preserve). This removes the js-yaml and PyYAML dependencies and dramatically speeds up serialization for large specs (on the Azure network spec, end-to-end serialization dropped from ~29s to ~0.2s). The emit-yaml-only option is renamed to emit-codemodel-only.

@azure-sdk-automation

azure-sdk-automation Bot commented Jul 6, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Replace the flatted wire format with the same $id/$ref reference-preserving
convention the C# emitter uses (System.Text.Json ReferenceHandler.Preserve):
objects become {"$id": "N", ...}, arrays become {"$id": "N", "$values": [...]},
and repeated/cyclic references become {"$ref": "N"}.

Unlike the C# writer, cycles are preserved (not dropped) because the Python
code model genuinely contains them. Validated on the Azure network spec: the
reconstructed graph is structurally identical (35175 objects, 32075 arrays,
3739/2855 shared, 1022 cycle edges) and round-trips stably.

- Add emitter/src/code-model-serializer.ts ($id/$ref serializer)
- Rewrite pygen/_codemodel_json.py loads/dumps for the $id/$ref dialect
- Drop the flatted dependency
# Conflicts:
#	packages/http-client-python/emitter/src/emitter.ts
#	packages/http-client-python/emitter/src/external-process.ts
@msyyc

msyyc commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

This PR will cause some code diff in generated sdk code. Most are just order change but there is one change https://github.com/Azure/azure-sdk-for-python/pull/47940/changes#r3542560807 that may need more investigation.

@timotheeguerin

Copy link
Copy Markdown
Member Author

yeah @msyyc this was just a POC to investigate gains but definitely will need to be designed/implemented more seriously if you want to move in that direction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:python Issue for the Python client emitter: @typespec/http-client-python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants