swift-json-schema-codegen

0.4.0

Typed JSON Schema code generation for Swift: shared core, macro, CLI, and SwiftPM plugin.
ajevans99/swift-json-schema-codegen

What's New

0.4.0 - Xcode plugin fix and OpenAPI separation

2026-09-17T21:16:57Z

Breaking changes

  • Removed OpenAPISchemaGenerator and GeneratedOpenAPISchema from JSONSchemaCodegenCore, along with the OpenAPI components example. Use Swift OpenAPI Schema Codegen for OpenAPI generation. Generic JSON Schema generation APIs remain available. (#12)
  • Removed OpenAPI-specific model-naming heuristics. Generated names may change for schemas whose paths contain components or schemas; regenerate and review checked-in output when upgrading.

Fixes

  • Fixed Xcode builds failing with Build input file cannot be found: .../JSONSchemaCodegenCLI. The executable target and plugin tool lookup now match the existing json-schema-codegen product name. Public CLI commands and library/plugin product names are unchanged. (#14, fixes #13)

Full changelog: v0.3.0...v0.4.0

Swift JSON Schema Codegen

CI Swift versions Platforms

Generate Swift types and JSON parsers from JSON Schema. Define a schema inline with @Schema, or generate Swift source from .schema.json files using the CLI or SwiftPM build plugin.

The generated code uses JSONSchemaBuilder to parse JSON and validate it against the schema. Output can be tuples or named models; it is not Codable synthesis or an HTTP client generator.

Installation

Requires Swift 6.1 or later. Deployment targets are macOS 14, iOS 17, tvOS 17, watchOS 10, Mac Catalyst 17, and visionOS 1 or later. The CLI and generation core also support Linux.

Add the package dependency to Package.swift:

dependencies: [
  .package(
    url: "https://github.com/ajevans99/swift-json-schema-codegen.git",
    from: "0.3.0"
  )
]

Then add the library to your target's dependencies:

.product(name: "JSONSchemaCodegen", package: "swift-json-schema-codegen")

SwiftPM resolves the JSON Schema runtime dependency automatically.

Quick start

import JSONSchemaCodegen

@Schema(
  """
  {
    "type": "object",
    "properties": {
      "name": { "type": "string", "minLength": 1 },
      "age": { "type": "integer", "minimum": 0 }
    },
    "required": ["name"],
    "additionalProperties": false
  }
  """,
  output: .models
)
enum PersonSchema {}

let person: PersonSchema.Value = try PersonSchema.schema.parseAndValidate(
  instance: #"{"name":"Ada","age":36}"#
)

print(person.name) // Ada
// person.age is Int? because "age" is not required.

@Schema adds a static schema member and, in model mode, named types inside the enum. Here, PersonSchema.Value is an immutable Sendable struct with name: String and age: Int?. Missing required fields, negative ages, and unknown properties cause parseAndValidate to throw.

The macro takes a string literal and must be attached to an empty enum outside generic contexts. Invalid schemas produce compiler diagnostics with a JSON Pointer identifying the problem.

Choosing an output type

Use output: .models when you want named types, initializers, and typed string enums. Omitting it uses the default tuple output: the example above would return (name: String, age: Int?) without generating a Value model.

Two details are worth knowing before choosing:

  • In tuple mode, an object with one property returns that property's value, not a one-field tuple. An object with no declared properties returns Void.
  • Optional and nullable are different. An optional nullable string is String??: nil means absent, while .some(nil) means JSON null.

Use parseAndValidate for input validation. parse performs typed conversion but does not check every schema constraint. Model initializers do not validate constraints either.

See output types and schema support for collections, unions, recursion, and validation limits.

Generate from files

Command-line tool

From a checkout of this repository:

swift run json-schema-codegen \
  --output-style models \
  --output-directory Generated \
  Examples/PluginExample/Sources/PluginExample/Schemas/Common/design-tokens.schema.json \
  Examples/PluginExample/Sources/PluginExample/Schemas/theme.schema.json

This writes DesignTokensSchema.generated.swift and ThemeSchema.generated.swift. Each contains a public namespace enum with a static schema member and its generated models.

Include the generated Swift in your target. It imports JSONSchema and JSONSchemaBuilder; linking JSONSchemaCodegen as above makes those modules available. Schemas are compiled into the generated code, so the input files are not needed at runtime.

Pass all referenced schema files in the same invocation. References are resolved offline: a $ref URL is an identifier, not a request to download a schema.

SwiftPM build plugin

For generation during a build, attach the plugin to your target:

.executableTarget(
  name: "Example",
  dependencies: [
    .product(name: "JSONSchemaCodegen", package: "swift-json-schema-codegen")
  ],
  exclude: ["json-schema-codegen.json"],
  resources: [.copy("Schemas")],
  plugins: [
    .plugin(name: "JSONSchemaCodegenPlugin", package: "swift-json-schema-codegen")
  ]
)

Put your .schema.json files in Sources/Example/Schemas/ and create Sources/Example/json-schema-codegen.json:

{
  "version": 1,
  "output": "models"
}

The plugin generates and compiles the Swift sources automatically. It discovers schemas recursively under the target directory and resolves them as one batch. The resource declaration avoids SwiftPM's unhandled-file warnings; the generated parsers do not load those resources.

See the complete plugin example or the generation guide for configuration, filename rules, naming overrides, and the core API.

Scope and documentation

The generator targets JSON Schema 2020-12, including composition, local and cross-document references, and recursive schemas. It does not support custom dialects or every possible Swift representation of a schema. Validation and typed output are separate: a constraint can be enforced without appearing as a Swift field or type.

Guide Contents
Output types and schema support Type mapping, string enums, recursion, supported keywords, and limits
Generation CLI options, plugin configuration, naming, references, and core APIs
Shared schemas and encoding Multiple roots sharing model types, and mapping models back to JSONValue
Official meta-schema example Offline generation from the official 2020-12 meta-schemas

For OpenAPI generation, use Swift OpenAPI Schema Codegen.

Development

Run the package tests from the repository root:

swift test

The CI workflow also runs generated-code consumers on macOS and Linux. For a local end-to-end check of the CLI and plugin:

bash Tests/CLI/smoke.sh

On macOS with Xcode installed, also run the Xcode build-system regression check:

bash Tests/CLI/xcode-smoke.sh

It builds and runs the plugin example with fresh DerivedData, retaining logs under .build/xcode-smoke.*. To build it interactively, open Examples/PluginExample/PluginExample.xcworkspace and select the PluginExample scheme. The CLI product, executable target, and plugin tool lookup all use json-schema-codegen so Xcode locates the generated tool executable correctly.

The conformance harness checks generated code against the official JSON Schema Test Suite. Its README covers fixture setup, measured coverage, and known failures.

License

MIT. See LICENSE.

Description

  • Swift Tools 6.1.0
View More Packages from this Author

Dependencies

Last updated: Sun Oct 25 2026 15:18:11 GMT-0900 (Hawaii-Aleutian Daylight Time)