Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

JSONSchema

A Swift library for working with JSON Schema definitions — especially for declaring schemas for AI tool use.

This library implements core features of the JSON Schema standard, targeting the draft-2020-12 version.

🙅‍♀️ This library specifically does not support the following features:

  • Document validation
  • Reference resolution
  • Conditional validation keywords, like dependentRequired, dependentSchemas, and if/then/else
  • Custom vocabularies and meta-schemas

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies:[.package(url:"https://github.com/mattt/JSONSchema.git", from:"1.3.0")]

Usage

Creating JSON Schemas with Dictionary Literals

Create JSON Schema definitions with Swift's expressive dictionary literal syntax:

import JSONSchema
// Example of defining a schema for an AI tool
letgetWeatherSchema:JSONSchema=.object(
properties:["location":.string(
description:"The city and state/country, e.g. 'San Francisco, CA'",
examples:["London, UK","Tokyo, Japan"]),"unit":.string(
description:"The temperature unit to use",
enum:["celsius","fahrenheit"],
default:"celsius"),"include_forecast":.boolean(
description:"Whether to include the weather forecast",
default:false)],
required:["location"])
// Complex schema with nested objects
letaddressSchema:JSONSchema=["street":.string(),"city":.string(),"zip":.string(pattern:"^[0-9]{5}$")]letorderSchema:JSONSchema=["name":.string(minLength:2, maxLength:100),"email":.string(format:.email),"address": addressSchema,"tags":.array(items:.string()),"status":.oneOf([.string(enum:["active","inactive","pending"]),.object(
properties:["error":.boolean(const:true),"code":.integer(enum:[400,401,403,404]),"message":.string(
description:"Detailed error message",
examples:["Invalid credentials","Not found"])],
required:["error"],
additionalProperties:false)])]

Working with JSON Values

The library provides a JSONValue type that represents any valid JSON value:

import JSONSchema
// Create JSON values
letnullValue:JSONValue=.null
letboolValue:JSONValue=trueletnumberValue:JSONValue=42letstringValue:JSONValue="hello"letarrayValue:JSONValue=[1,2,3]letobjectValue:JSONValue=["key":"value"]
// Extract typed values
iflet string = stringValue.stringValue {print(string) // "hello"
}iflet number = numberValue.intValue {print(number) // 42
}
// Use in schema definitions
letschema:JSONSchema=.object(
default:["name":"John Doe"],
examples:[["name":"Jane Doe","age":25]],
properties:["name":.string(),"age":.integer()])

Schema Properties

Access schema metadata and type information through convenience properties:

import JSONSchema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string,"age":.integer
])
// Access metadata
print(schema.typeName) // "object"
print(schema.title) // "Person"
print(schema.description) // "A human being"

JSON Value Compatibility

The library provides methods to check compatibility between JSON values and schemas:

import JSONSchema
// Check if a JSON value is compatible with a schema
letvalue:JSONValue=42letschema:JSONSchema=.integer(minimum:0)letisCompatible= value.isCompatible(with: schema) // true
// Strict vs non-strict compatibility
letnumberValue:JSONValue=42letnumberSchema:JSONSchema=.number()letstrictCompatible= numberValue.isCompatible(with: numberSchema) // false
letnonStrictCompatible= numberValue.isCompatible(with: numberSchema, strict:false) // true

Schema Serialization

import JSONSchema
// Create a schema
letschema:JSONSchema=.object(
title:"Person",
description:"A human being",
properties:["name":.string(),"age":.integer(minimum:0)],
required:["name"])
// Encode to JSON
letencoder=JSONEncoder()
encoder.outputFormatting =[.prettyPrinted]letjsonData=try encoder.encode(schema)print(String(data: jsonData, encoding:.utf8)!)
// Decode from JSON
letdecoder=JSONDecoder()letdecodedSchema=try decoder.decode(JSONSchema.self, from: jsonData)

Preserving Property Order

According to the JSON spec (emphasis added):

6. Objects

[...] The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. [...]

And yet, JSON Schema documents often do assign significance to the order of properties. In such cases, it may be desireable to preserve this ordering. For example, ensuring that an auto-generated form for a createEvent tool lists start before end. For this reason, the associated value for JSONSchema.object properties use the OrderedDictionary type from apple/swift-collections

By default, JSONDecoder doesn't guarantee stable ordering of keys. However, this package provides the following affordances to decode JSONSchema objects with properties in order they appear in the JSON string:

  • A static extractSchemaPropertyOrder method that extracts property order from the top-level "properties" field of a JSON Schema object.
  • A static extractPropertyOrder method that extracts property order from any JSON object at a specified keypath.
  • A static propertyOrderUserInfoKey constant that you can pass to JSONDecoder (determined with either extraction method or some other means) to guide the ordering of JSON Schema object properties.
letjson="""{"type": "object","properties": {"firstName": {"type": "string"},"lastName": {"type": "string"},"age": {"type": "integer"},"email": {"type": "string", "format": "email"} }}""".data(using:.utf8)!
// Extract property order from a JSON Schema object's "properties" field
iflet propertyOrder =JSONSchema.extractSchemaPropertyOrder(from: jsonData){
// Configure decoder to preserve order
letdecoder=JSONDecoder()
decoder.userInfo[JSONSchema.propertyOrderUserInfoKey]= propertyOrder
// Decode with preserved property order
letschema=try decoder.decode(JSONSchema.self, from: data)
// Properties will maintain their original order: `firstName`, `lastName`, `age`, `email`
}
// Or extract from a nested object using a keypath
letnestedJSONData="""{"definitions": {"person": {"firstName": "John","lastName": "Doe" } }}""".data(using:.utf8)!
letkeyOrder=JSONSchema.extractPropertyOrder(from: nestedJSONData,
at:["definitions","person"])
// keyOrder will be ["firstName", "lastName"]

Motivation

There are a few other packages out there for working with JSON Schema, but they did more than I needed.

This library focuses solely on defining and serializing JSON Schema values with a clean, ergonomic API.
That's it.

The implementation is deliberately minimal. At its core is one big JSONSchema enumeration with associated values for most of the JSON Schema keywords you might want. No result builders, property wrappers, macros, or dynamic member lookup — just old-school Swift with choice conformance to ExpressibleBy___Literal 💅

License

This project is available under the MIT license. See the LICENSE file for more info.

About

A Swift library for working with JSON Schema definitions — especially for AI tool use.

Topics

Resources

Stars

56 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages