The canonical pattern for bidirectional conversion between JSON Schema and GraphQL SDL.
This project establishes a standard for extending JSON Schema with GraphQL-specific metadata using x-graphql-* vendor extensions. It addresses the fundamental impedance mismatch between JSON Schema's validation-first model and GraphQL's type system, enabling a validation-first workflow while maintaining full GraphQL expressiveness.
Organizations often have to choose between:
- Schema-first (SDL): Great for API design, but lacks robust data validation capabilities.
- Code-first: flexible, but loses the benefits of a declarative schema.
- JSON Schema-first: Great for validation, but difficult to expose as a GraphQL API without data loss.
Existing tools often perform "lossy" conversions, dropping directives, arguments, and type metadata.
We define a lossless mapping strategy using standard JSON Schema extensions.
- Single Source of Truth: JSON Schema defines both validation logic and API structure.
- Bidirectional: Convert JSON Schema ↔ GraphQL SDL without losing metadata.
- Upstream Interop: Bridge directly from Zod or Standard Schema using
@standard-schema/spec. - Downstream Codegen: Automatically pipe SDL outputs into
@graphql-codegenfor end-to-end TS interfaces. - Federation-Ready: Full support for Apollo Federation v2.9 directives.
- Strict Governance: Meta-schema rejects unknown
x-graphqlkeywords to prevent configuration drift.
Create a JSON Schema with x-graphql extensions:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"User": {
"type": "object",
"x-graphql-type-name": "User",
"x-graphql-type-kind": "OBJECT",
"x-graphql-federation-keys": [{ "fields": "id" }],
"properties": {
"user_id": {
"type": "string",
"x-graphql-field-name": "id",
"x-graphql-field-type": "ID",
"x-graphql-field-non-null": true
},
"username": {
"type": "string",
"minLength": 3,
"x-graphql-field-name": "username",
"x-graphql-field-type": "String"
}
}
}
}
}Using our converter, this generates the following SDL:
type User @key(fields: "id") {
id: ID!
username: String
}Node CLI (built output):
node converters/cli/dist/index.js \
--input examples/user-service.schema.json \
--output output/user-service.graphql \
--types output/user-service.d.ts \
--descriptions \
--preserve-order \
--include-federation-directives \
--federation-version V2 \
--naming-convention GRAPHQL_IDIOMATIC \
--id-strategy COMMON_PATTERNS \
--output-format SDLRust CLI (release binary jxql):
converters/rust/target/release/jxql \
--input examples/user-service.schema.json \
--output output/user-service.graphql \
--descriptions \
--preserve-order \
--include-federation-directives \
--federation-version V2 \
--naming-convention GRAPHQL_IDIOMATIC \
--id-strategy COMMON_PATTERNS \
--output-format SDLNotes:
--output-format AST_JSONemits the AST as JSON instead of SDL.--fail-on-warningexits non-zero if any warnings are produced.--id-strategyacceptsNONE,COMMON_PATTERNS, orALL_STRINGS(legacy--infer-idsmaps toCOMMON_PATTERNS).--types <path>enables automatic TypeScript typings generation via@graphql-codegen/core.
Example AST_JSON output (truncated):
{
"kind": "Document",
"definitions": [
{
"kind": "ObjectTypeDefinition",
"name": { "kind": "Name", "value": "User" },
"fields": [
{
"kind": "FieldDefinition",
"name": { "kind": "Name", "value": "id" },
"type": {
"kind": "NonNullType",
"type": {
"kind": "NamedType",
"name": { "kind": "Name", "value": "ID" }
}
}
}
]
}
]
}- Bidirectional Conversion: Lossless round-tripping between formats.
- Type System Complete: Supports Objects, Interfaces, Unions, Enums, Inputs, and Scalars.
- Field Arguments: Define arguments with default values in JSON Schema.
- Documentation: Preserves descriptions and deprecation reasons.
- Performance: Rust backend relies on
simd-jsonfor ultra-fast native SIMD processing. - Ecosystem Bridges: Built-in support for Zod and Standard Schema.
Fully supports the Apollo Federation specification:
- Entities:
@key,@shareable,@interfaceObject - Field Directives:
@external,@requires,@provides,@override - Authorization:
@authenticated,@requiresScopes,@policy - Viaduct Support: Deep integration with
@resolver,@backingData, and@idOf.
A major production application of the json-schema-x-graphql standard is emulating legacy or remote REST APIs as federated subgraphs to form a stitched API gateway. By combining lightweight registration manifests (endpoints-config.yaml) and extended JSON Schemas, you can unify separate microservices (e.g., forward geocoding, reverse coordinates lookup, IP routing, and ZIP code services) into a single, cohesive federated schema.
The emulation proxy engine performs two core translation phases during query execution:
- Request Translation: The engine reads the incoming GraphQL queries, fields, arguments, or federation entity representations (e.g.,
{ args: { q: "Berlin" } }or{ representations: { latitude: "52.51", longitude: "13.39" } }). It dynamically interpolates these parameters into the registered endpoint templates inendpoints-config.yamlto fire downstream requests to the remote REST endpoints. - Response Translation: The engine intercepts raw REST JSON response payloads and routes them through a recursive adapter. The adapter leverages the
x-graphql-field-nameandx-graphql-type-namerules declared in our JSON Schemas (automatically applying IDIOMATIC camelCase field formatting and type conversions, and resolving local$refpointers) to map raw keys into clean, typed camelCase GraphQL objects.
A complete runnable implementation orchestrating four live geocoding REST microservices using this pattern is available in our mesh-gateway workspace package.
The project includes a powerful web-based editor featuring:
- Three-Panel Layout: Simultaneous view of JSON Schema, GraphQL SDL, and Visual Graph.
- Real-time Sync: Changes in one view instantly propagate to others.
- Visual Graph: Interactive node-link diagram of your schema structure.
To handle naming conflicts and conventions cleanly, we use three distinct namespaces:
snake_case: JSON Schema properties (optimized for database/backend).camelCase: GraphQL fields (optimized for API consumers).hyphen-case: Extension keys (e.g.,x-graphql-field-name).
- Core Converters: Implemented in Rust (for WASM/Performance) and Node.js (for ease of use).
- Frontend: React-based editor using Monaco Editor and
graphql-editorfor visualization. - Collaboration: Built with Yjs/Loro architecture for future multi-user editing.
Current Version: 0.4.0 (Beta) Status: Core Implementation & Web Editor Complete
- Phase 1: Foundation
- Meta-schema definition (JSON Schema 2020-12)
- Comprehensive example schemas
- Architecture documentation
- Phase 2: Core Converters
- ✅ Rust converter (WASM-ready, SIMD optimized)
- ✅ Node.js converter (TypeScript, Codegen/Zod interop)
- ✅ Bidirectional fidelity verification
- Phase 3: Web Editor
- ✅ React split-pane editor
- ✅ Visual Graph integration
- ✅ Real-time bidirectional conversion
- Phase 4: Architecture Governance
- ✅ Strict Meta-Schema closures
- ✅ Native Zod and Standard Schema integrations
- ✅ Seamless GraphQL-Codegen output pipeline
- Performance Benchmarking
- Rust SIMD benchmark suite calibration
- Cross-browser validation
- Phase 5: Release
- npm/crates.io publication
- Public demo deployment
npm install @json-schema-x-graphql/coreimport { jsonSchemaToGraphQL } from "@json-schema-x-graphql/core";
const sdl = jsonSchemaToGraphQL(myJsonSchema);
console.log(sdl);[dependencies]
json-schema-x-graphql = "0.4.0"We welcome contributions! Please see CONTRIBUTING.md for details on how to get started.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.