{"id":15102762,"url":"https://github.com/objecthub/swift-dynamicjson","last_synced_at":"2026-01-20T10:32:30.669Z","repository":{"id":222265682,"uuid":"756047312","full_name":"objecthub/swift-dynamicjson","owner":"objecthub","description":"Framework for representing, validating, querying, and manipulating generic JSON values in Swift. Supported are standards such as JSON Pointer (RFC 6901), JSON Path (RFC 9535), JSON Patch (RFC 6902), JSON Merge Patch (RFC 7396), and JSON Schema.","archived":false,"fork":false,"pushed_at":"2025-04-12T16:56:32.000Z","size":660,"stargazers_count":178,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-10-10T13:45:47.935Z","etag":null,"topics":["json","json-merge-patch","json-parser","json-patch","json-path","json-pointer","json-schema","json-schema-validator"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/objecthub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-11T20:28:13.000Z","updated_at":"2025-09-26T10:14:41.000Z","dependencies_parsed_at":"2024-04-13T21:45:37.277Z","dependency_job_id":null,"html_url":"https://github.com/objecthub/swift-dynamicjson","commit_stats":null,"previous_names":["objecthub/swift-dynamicjson"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/objecthub/swift-dynamicjson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objecthub%2Fswift-dynamicjson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objecthub%2Fswift-dynamicjson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objecthub%2Fswift-dynamicjson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objecthub%2Fswift-dynamicjson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/objecthub","download_url":"https://codeload.github.com/objecthub/swift-dynamicjson/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objecthub%2Fswift-dynamicjson/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28601834,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T09:39:28.479Z","status":"ssl_error","status_checked_at":"2026-01-20T09:38:10.511Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-merge-patch","json-parser","json-patch","json-path","json-pointer","json-schema","json-schema-validator"],"created_at":"2024-09-25T19:06:11.068Z","updated_at":"2026-01-20T10:32:30.655Z","avatar_url":"https://github.com/objecthub.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swift DynamicJSON\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fobjecthub%2Fswift-dynamicjson%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/objecthub/swift-dynamicjson) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fobjecthub%2Fswift-dynamicjson%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/objecthub/swift-dynamicjson) [![IDE: Xcode 16](https://img.shields.io/badge/IDE-Xcode%2016-blue.svg?style=flat)](https://developer.apple.com/xcode/) [![Package managers: SwiftPM, Carthage](https://img.shields.io/badge/Package%20managers-SwiftPM,%20Carthage-green.svg?style=flat)](https://github.com/Carthage/Carthage) [![License: Apache](http://img.shields.io/badge/License-Apache-lightgrey.svg?style=flat)](https://raw.githubusercontent.com/objecthub/swift-numberkit/master/LICENSE)\n\n_DynamicJSON_ is a framework for representing, querying, and manipulating generic JSON values. The framework provides:\n\n   - A generic representation of JSON values as defined by [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259/).\n   - A natural embedding of functionality for creating and manipulating JSON values into the Swift programming language, including support for reading and writing JSON data and for converting typed and untyped JSON representations.\n   - An implementation of _JSON Pointer_ as defined by [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901/) for locating values within a JSON document.\n   - An implementation of _JSON Path_ as defined by [RFC 9535](https://datatracker.ietf.org/doc/html/rfc9535/) for querying JSON data.\n   - An implementation of _JSON Patch_ as defined by [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/) for mutating JSON data.\n   - An implementation of _JSON Merge Patch_ as defined by [RFC 7396](https://datatracker.ietf.org/doc/html/rfc7396/) for merging JSON data with JSON patches.\n   - An implementation of _JSON Schema_ as defined by the [2020-12 Internet Draft specification](https://datatracker.ietf.org/doc/draft-bhutton-json-schema/) for validating JSON data.\n\n\u003ctable width=\"100%\"\u003e\n\u003ctr\u003e\u003cth colspan=\"2\"\u003eTable of contents\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"650px\" valign=\"top\"\u003e\n1. \u0026nbsp;\u003ca href=\"#representing-json-data\"\u003eRepresenting JSON Data\u003c/a\u003e\u003cbr /\u003e\n2. \u0026nbsp;\u003ca href=\"#accessing-json-values\"\u003eAccessing JSON Values\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 2.1 \u0026nbsp;\u003ca href=\"#json-location\"\u003eJSON Location\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 2.2 \u0026nbsp;\u003ca href=\"#json-pointer\"\u003eJSON Pointer\u003c/a\u003e\u003cbr /\u003e\n3. \u0026nbsp;\u003ca href=\"#queries-with-json-path\"\u003eQueries with JSON Path\u003c/a\u003e\u003cbr /\u003e\n4. \u0026nbsp;\u003ca href=\"#mutating-json-values\"\u003eMutating JSON Values\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 4.1 \u0026nbsp;\u003ca href=\"#mutation-api\"\u003eMutation API\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 4.2 \u0026nbsp;\u003ca href=\"#json-patch\"\u003eJSON Patch\u003c/a\u003e\u003cbr /\u003e\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n5. \u0026nbsp;\u003ca href=\"#merging-json-values\"\u003eMerging JSON Values\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 5.1 \u0026nbsp;\u003ca href=\"#symmetrical-merge\"\u003eSymmetrical Merge\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 5.2 \u0026nbsp;\u003ca href=\"#overriding-merge\"\u003eOverriding Merge\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 5.3 \u0026nbsp;\u003ca href=\"#json-merge-patch\"\u003eJSON Merge Patch\u003c/a\u003e\u003cbr /\u003e\n6. \u0026nbsp;\u003ca href=\"#validating-json-data\"\u003eValidating JSON Data\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 6.1 \u0026nbsp;\u003ca href=\"#implementation-overview\"\u003eImplementation Overview\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 6.2 \u0026nbsp;\u003ca href=\"#validation-api\"\u003eValidation API\u003c/a\u003e\u003cbr /\u003e\n\u0026nbsp;\u0026nbsp; 6.3 \u0026nbsp;\u003ca href=\"#metadata-and-defaults\"\u003eMetadata and Defaults\u003c/a\u003e\u003cbr /\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u0026nbsp;\n\n## Representing JSON Data\n\nAll JSON values in framework _DynamicJSON_ are represented with enumeration [`JSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSON.swift).\nEnumeration `JSON` defines the following cases:\n\n```swift\nindirect enum JSON: Hashable, Codable, CustomStringConvertible, ... {\n  case null\n  case boolean(Bool)\n  case integer(Int64)\n  case float(Double)\n  case string(String)\n  case array([JSON])\n  case object([String : JSON])\n  ...\n}\n```\n\nJSON values can be easily constructed using Swift literal syntax. Here is an example\nfor the initialization of a small JSON-based data structure:\n\n```swift\nlet json0: JSON = [\n  \"foo\": true,\n  \"str\": \"one two\",\n  \"object\": [\n    \"value\": nil,\n    \"arr\": [1, 2, 3],\n    \"obj\": [ \"x\" : 17.6 ]\n  ]\n]\n```\n\nThere are also [initializers](https://github.com/objecthub/swift-dynamicjson/blob/b53ea8d5a649a1132e44ac9ea9c20dd403549754/Sources/DynamicJSON/JSON.swift#L219)\nto convert JSON encoded data in the form of a\n[`String`](https://developer.apple.com/documentation/swift/string) or a\n[`Data`](https://developer.apple.com/documentation/foundation/data) object into a\n[`JSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSON.swift)\nenumeration. The following code initializes a JSON value from a JSON encoded value in a String\nliteral.\n\n```swift\nlet json1 = try JSON(string: \"\"\"\n  {\n    \"foo\": true,\n    \"str\": \"one two\",\n    \"object\": {\n      \"value\": null,\n      \"arr\": [1, 2, 3],\n      \"obj\": { \"x\" : 17.6 }\n    }\n  }\n\"\"\")\n```\n\nAny encodable type can be converted into a JSON value using the initializer `init(encodable:)`.\nAlternatively, `init()` can be used. This is the most generic initializer which can also\ncoerce basic types like `Bool`, `Int`, `String`, etc. into JSON.\n\n```swift\nstruct Person: Codable {\n  let name: String\n  let age: Int\n  let children: [Person]\n}\nlet person = Person(name: \"John\", age: 34,\n                    children: [ Person(name: \"Sofia\", age: 5, children: []) ])\nlet json2 = try JSON(encodable: person)\nprint(json2.description)\n```\n\nExecuting this code will print the following JSON-based representation of `Person`:\n\n```json\n{\n  \"age\" : 34,\n  \"children\" : [\n    {\n      \"age\" : 5,\n      \"children\" : [],\n      \"name\" : \"Sofia\"\n    }\n  ],\n  \"name\" : \"John\"\n}\n```\n\nIt is also possible to do the inverse, and convert a JSON-based representation\ninto a strongly typed data structure via method `coerce()`.\n\n```swift\nlet json3: JSON = [\n  \"name\": \"Matthew\",\n  \"age\": 29,\n  \"children\": []\n]\nlet person2: Person = try json3.coerce()\n```\n\n\n## Accessing JSON Values\n\nA JSON value within a larger JSON document can be identified and accessed using dynamic\nmember lookup as if the data was fully structured, e.g. by representing it as a struct.\nHere are several examples showcasing the different ways how to access the first element\nof array `arr` in `object` of `json1`. All expressions return the JSON value 1.\n\n   - **Dynamic member lookup:** `json1.object?.arr?[0]`\n   - **Keypath lookup:** `json1[keyPath: \\.object?.arr?[0]]`\n   - **Subscript lookup:** `json1[\"object\"]?[\"arr\"]?[0]`\n   - **Reference lookup:**\n      - Using JSON Pointer string: `try json1[ref: \"/object/arr/0\"]`\n      - Using JSON Path string: `try json1[ref: \"$.object.arr[0]\"]`\n      - Using implementations of [`JSONReference`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONReference.swift), such as `JSONPointer` and `JSONPath`: `json1[ref: p]`, where `p` is an object of type `JSONReference`\n\nIn _DynamicJSON_, components of a JSON value are identified by implementations\nof the protocols [`JSONReference`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONReference.swift) and [`SegmentableJSONReference`](https://github.com/objecthub/swift-dynamicjson/blob/5a14f6e014116be9c95c68f0e3141d2605f95c5e/Sources/DynamicJSON/JSONReference.swift#L57). The following code presents the core methods implementing JSON references:\n\n```swift\nprotocol JSONReference: CustomStringConvertible {\n  // Returns a new JSONReference with the given member selected.\n  func select(member: String) -\u003e Self\n  // Returns a new JSONReference with the given index selected.\n  func select(index: Int) -\u003e Self\n  // Retrieve value at which this reference is pointing from JSON document `value`.\n  func get(from value: JSON) -\u003e JSON?\n  // Replace value at which this reference is pointing with `json` within `value`.\n  func set(to json: JSON, in value: JSON) throws -\u003e JSON\n  // Mutate value at which this reference is pointing within JSON document `value`\n  // with function `proc`.\n  func mutate(_ json: inout JSON, with proc: (inout JSON) throws -\u003e Void) throws\n}\n\nprotocol SegmentableJSONReference: JSONReference {\n  associatedtype Segment: JSONReferenceSegment\n  // An array of segments representing the reference.\n  var segments: [Segment] { get }\n  // Creates a new `SegmentableJSONReference` on top of this reference.\n  func select(segment: Segment) -\u003e Self\n  // Decomposes this reference into the top segment selector and its parent.\n  var deselect: (Self, Segment)? { get }\n}\n```\n\n_DynamicJSON_ currently provides two implementations of `SegmentableJSONReference`: [`JSONPointer`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPointer.swift) and [`JSONLocation`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONLocation.swift), an abstraction that is equivalent to singular _JSON Path_ queries.\n\n### JSON Location\n\n[`JSONLocation`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONLocation.swift) is the default implementation for identifying JSON values within a JSON document. It is based on how values are identified in [JSON Path](https://datatracker.ietf.org/doc/html/rfc9535/) and uses a restricted form of JSON Path query syntax.\n\nA `JSONLocation` value is defined in terms of a sequence of member names and array indices used to navigate through the structure of a JSON document. `JSONLocation` references refer to at most one value within a JSON document. The following code summarizes how `JSONLocation` values are represented:\n\n```swift\nindirect enum JSONLocation: SegmentableJSONReference, Codable, Hashable, CustomStringConvertible {\n  case root\n  case member(JSONLocation, String)\n  case index(JSONLocation, Int)\n  \n  enum Segment: JSONReferenceSegment, Codable, Hashable, CustomStringConvertible {\n    case member(String)\n    case index(Int)\n    ...\n  }\n  ...\n}\n```\n\nA JSON location is a path to an element in a JSON structure. Each element of the path is called a _segment_. The JSON location syntax supports two different forms to express such sequences of segments. Each sequence starts with `$` indicating the \"root\" of a JSON document. The most common form for expressing the segment sequence is using the dot notation:\n\n```\n$.store.book[0].title\n```\n\nWhile accessing an array index is always done using bracket notation, it is possible to also express the access of members of an object using bracket notation:\n\n```\n$['store']['book'][0]['title']\n```\n\nIs is also possible to mix the dot and bracket notation. Dots are only used before property names and never together with brackets:\n\n```\n$['store'].book[-1].title\n```\n\nThe previous example also shows the usage of negative indices, which are interpreted as offsets\nfrom the end of arrays with -1 referring to the last element.\n\nThe `JSONLocation` API supports multiple initializers for creating JSON location references:\n\n```swift\nlet r1 = try JSONLocation(\"$['store']['book'][0]['title']\")\nlet r2 = JSONLocation(segments: [.member(\"store\"),\n                                 .member(\"book\"),\n                                 .index(0),\n                                 .member(\"title\")])\n```\n\n`JSONLocation` defines the following frequently used methods:\n\n```swift\nindirect enum JSONLocation: SegmentableJSONReference, ... {\n  // The segments defining this `JSONLocation`.\n  var segments: [Segment]\n  // Returns a new JSONLocation with the given member selected.\n  func select(member: String) -\u003e JSONLocation\n  // Returns a new JSONLocation with the given index selected.\n  func select(index: Int) -\u003e JSONLocation\n  // Returns a new JSONLocation by appending the given segment.\n  func select(segment: Segment) -\u003e JSONLocation\n  // Returns a matching `JSONPointer` reference if possible.\n  var pointer: JSONPointer?\n  // Returns a matching `JSONPath` query.\n  var path: JSONPath\n  // Retrieve value at this location within `value`.\n  func get(from value: JSON) -\u003e JSON?\n  // Replace value at this location within `in` with `value`.\n  func set(to json: JSON, in value: JSON) throws -\u003e JSON\n  // Mutate value at this location within `value` with function `proc`.\n  // `proc` is provided a reference, enabling efficient in-place mutations.\n  func mutate(_ json: inout JSON, with proc: (inout JSON) throws -\u003e Void) throws\n}\n```\n\n### JSON Pointer\n\n_JSON Pointer_ is specified by [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901/) and\nis generally the most established formalism for referring to a JSON value within a JSON document.\nJSON Pointer is intended to be easily expressed in JSON string values as well as Uniform Resource\nIdentifier (URI) fragment identifiers (see [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986/)).\n\nLike JSON Locations, each JSON Pointer specifies a path to an element in a JSON structure starting\nwith its root. Each element of the path either refers to an object member or an array index.\nSyntactically, each path element is prefixed with \"/\". JSON Pointer uses \"\u0026#126;1\" to encode \"/\" in\nmember names and \"\u0026#126;0\" to encode \"\u0026#126;\". The empty string refers to the root of the JSON document.\nHere is an example:\n\n```\n/store/book/0/title\n```\n\nJSON Pointer neither supports forcing an element such as \"/0\" to refer to an array index, nor\ndoes it allow for negative indices (as an offset from the end of the array). All numeric path\nelements such as \"0\" above can either match an array and select index 0 or they match an object\nmember \"0\". Thus, there is no general way to map JSON Location into JSON Pointer or vice versa.\n\nStruct [`JSONPointer`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPointer.swift)\nimplements the JSON Pointer standard in the following way:\n\n```swift\nstruct JSONPointer: SegmentableJSONReference, Codable, Hashable, CustomStringConvertible {\n  let segments: [ReferenceToken]\n  \n  enum ReferenceToken: JSONReferenceSegment, Hashable, CustomStringConvertible {\n    case member(String)\n    case index(String, Int?)\n    ...\n  }\n  ...\n}\n```\n\nThe `JSONPointer` API supports multiple initializers for creating JSON Pointer references:\n\n```swift\nlet p1 = try JSONPointer(\"/store/book/0/title\")\nlet p2 = JSONPointer(components: [\"store\", \"book\", \"0\", \"title\"])\n```\n\n`JSONPointer` defines the following frequently used methods:\n\n```swift\nstruct JSONPointer: SegmentableJSONReference, ... {\n  // Returns this JSONPointer as an array of reference tokens.\n  var segments: [ReferenceToken]\n  // Returns a new JSONPointer with the given member selected.\n  func select(member: String) -\u003e JSONPointer\n  // Returns a new JSONPointer with the given index selected.\n  func select(index: Int) -\u003e JSONPointer\n  // Constructs a new JSONPointer by appending the given segment to this pointer.\n  func select(segment: ReferenceToken) -\u003e JSONPointer\n  // Decomposes this JSONPointer into a parent pointer and a selector reference token.\n  var deselect: (JSONPointer, ReferenceToken)?\n  // The reference tokens defining this `JSONPointer` value.\n  var components: [String]\n  // Returns all JSON locations corresponding to this `JSONPointer`.\n  func locations() -\u003e [JSONLocation]\n  // Retrieve value at which this reference is pointing from JSON document `value`.\n  func get(from value: JSON) -\u003e JSON?\n  // Replace value at which this reference is pointing with `json` within `value`.\n  func set(to json: JSON, in value: JSON) throws -\u003e JSON\n  // Mutate value at this location within `value` with function `proc`. `proc`\n  // is provided a reference, enabling efficient, in-place mutations.\n  func mutate(_ json: inout JSON, with proc: (inout JSON) throws -\u003e Void) throws\n}\n```\n\n## Queries with JSON Path\n\n_DynamicJSON_ supports the full _JSON Path_ standard as defined by [RFC 9535](https://datatracker.ietf.org/doc/html/rfc9535/).\nEnum [`JSONPath`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPath/JSONPath.swift)\nrepresents JSON Path queries.\n[`JSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSON.swift)\nprovides `query()` methods to apply a JSON Path query to a JSON value.\n\nTo illustrate the usage of JSON Path queries, the following JSON value is being defined (this\nis the example from RFC 9535):\n\n```swift\nlet jval = try JSON(string: \"\"\"\n  { \"store\": {\n      \"book\": [\n        { \"category\": \"reference\",\n          \"author\": \"Nigel Rees\",\n          \"title\": \"Sayings of the Century\",\n          \"price\": 8.95 },\n        { \"category\": \"fiction\",\n          \"author\": \"Evelyn Waugh\",\n          \"title\": \"Sword of Honour\",\n          \"price\": 12.99 },\n        { \"category\": \"fiction\",\n          \"author\": \"Herman Melville\",\n          \"title\": \"Moby Dick\",\n          \"isbn\": \"0-553-21311-3\",\n          \"price\": 8.99 },\n        { \"category\": \"fiction\",\n          \"author\": \"J. R. R. Tolkien\",\n          \"title\": \"The Lord of the Rings\",\n          \"isbn\": \"0-395-19395-8\",\n          \"price\": 22.99 }\n      ],\n      \"bicycle\": {\n        \"color\": \"red\",\n        \"price\": 399\n      }\n    }\n  }\n  \"\"\")\n```\n\nNow a JSON Path query `$.store.book[?@.price \u003c 10].title` can be defined by using the\n`JSONPath(query:strict:)` initializer. Finally, the path can be applied to `jval` by\ninvoking its `query()` method. The result is an array of\n[`LocatedJSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/LocatedJSON.swift)\nvalues matching the query within `jval`.\n[`LocatedJSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/LocatedJSON.swift)\ncombines a location where a value was found with the value at that location into one object.\n\n```swift\nlet path = try JSONPath(query: \"$.store.book[?@.price \u003c 10].title\")\nvar results = try value.query(path)\nfor result in results {\n  print(result)\n}\n```\n\nThis is the output generated from this code. It prints two `LocatedJSON` objects for the two\nvalues within `jval` matching the query `path`.\n\n```swift\n$['store']['book'][0]['title'] =\u003e \"Sayings of the Century\"\n$['store']['book'][2]['title'] =\u003e \"Moby Dick\"\n```\n\nIf only locations or only values are needed as a result of evaluating a JSON Path query, then\nit is possible to use the `query(locations:)` or `query(values:)` methods of `JSON`.\n\nThe above API supports the default JSON Path query language. JSON Path has a built-in\nextensibility mechanism that lets one add custom functions, applicable in query filters.\nThis can be achieved by extending class\n[`JSONPathEnvironment`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPath/JSONPathEnvironment.swift)\nand overriding method `initialize()`. Such an extended environment can then be passed to\nthe initializer of struct \n[`JSONPathEvaluator`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPath/JSONPathEvaluator.swift),\nwhich provides a means to execute queries using the extended environment.\n\n## Mutating JSON Values\n\n### Mutation API\n\n_DynamicJSON_ represents JSON data with value type\n[`JSON`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSON.swift).\nThere are a number of methods that mutate such data without copies being created. These are listed\nin the code snippet below.\n\n```swift\nenum JSON: Hashable, ... {\n  // Mutates this JSON value if it represents either an array or a string by\n  // appending the given JSON value `json`. For arrays, `json` is appended as a\n  // new element. For strings it is expected that `json` also refers to a string\n  // and `json` gets appended as a string. For all other types of JSON values,\n  // an error is thrown.\n  mutating func append(_ json: JSON) throws\n  \n  // Mutates this JSON value if it represents either an array or a string by\n  // inserting the given JSON value `json`. For arrays, `json` is inserted as a\n  // new element at `index`. For strings it is expected that `json` also refers to\n  // a string and `json` gets inserted into this string at position `index`. For\n  // all other types of JSON values, an error is thrown.\n  mutating func insert(_ json: JSON, at index: Int) throws\n  \n  // Adds a new key/value mapping or updates an existing key/value mapping in this\n  // JSON object. If this JSON value is not an object, an error is thrown.\n  mutating func assign(_ member: String, to json: JSON) throws\n  \n  // Replaces the value the location reference `ref` is referring to with `json`.\n  // The replacement is done in place, i.e. it mutates this JSON value. `ref` can\n  // be implemented by any abstraction implementing the `JSONReference` procotol.\n  mutating func update(_ ref: JSONReference, with json: JSON) throws\n  \n  // Replaces the value the location reference string `ref` is referring to with\n  // `json`. The replacement is done in place, i.e. it mutates this JSON value.\n  // `ref` is a string representation of either `JSONLocation` or `JSONPointer`\n  // references.\n  mutating func update(_ ref: String, with json: JSON) throws\n  \n  // Mutates the JSON value the reference `ref` is referring to with function\n  // `proc`. `proc` receives a reference to the JSON value, allowing efficient in\n  // place mutations without automatically doing any copying. `ref` can be\n  // implemented by any abstraction implementing the `JSONReference` procotol.\n  mutating func mutate(_ ref: JSONReference,\n                       with proc: (inout JSON) throws -\u003e Void) throws\n  \n  // Mutates the JSON value the reference `ref` is referring to with function\n  // `arrProc` if the value is an array or `objProc` if the value is an object. For\n  // all other cases, an error is thrown. This method allows for efficient in place\n  // mutations without automatically doing any copying. `ref` can be implemented by\n  // any abstraction implementing the `JSONReference` procotol.\n  mutating func mutate(_ ref: JSONReference,\n                       array arrProc: ((inout [JSON]) throws -\u003e Void)? = nil,\n                       object objProc: ((inout [String : JSON]) throws -\u003e Void)? = nil,\n                       other proc: ((inout JSON) throws -\u003e Void)? = nil) throws\n  \n  // Mutates the JSON value the reference string `ref` is referring to with function\n  // `proc`. `proc` receives a reference to the JSON value, allowing efficient in\n  // place mutations without automatically doing any copying. `ref` is a string\n  // representation of either `JSONLocation` or `JSONPointer` references.\n  mutating func mutate(_ ref: String, with proc: (inout JSON) throws -\u003e Void) throws\n  \n  // Mutates the JSON array the reference string `ref` is referring to with function\n  // `arrProc` if the value is an array or `objProc` if the value is an object. For\n  // all other cases, an error is thrown. This method allows for efficient in place\n  // mutations without automatically doing any copying. `ref` is a string\n  // representation of either `JSONLocation` or `JSONPointer` references.\n  mutating func mutate(_ ref: String,\n                       array arrProc: ((inout [JSON]) throws -\u003e Void)? = nil,\n                       object objProc: ((inout [String : JSON]) throws -\u003e Void)? = nil,\n                       other proc: ((inout JSON) throws -\u003e Void)? = nil) throws\n  ...\n}\n```\n\nThe most generic form of mutation is provided by the following two methods:\n\n```swift\nmutating func mutate(_ ref: JSONReference,\n                     with proc: (inout JSON) throws -\u003e Void) throws\nmutating func mutate(_ ref: JSONReference,\n                     array arrProc: ((inout [JSON]) throws -\u003e Void)? = nil,\n                     object objProc: ((inout [String : JSON]) throws -\u003e Void)? = nil,\n                     other proc: ((inout JSON) throws -\u003e Void)? = nil) throws\n```\n\nThese methods mutate the JSON value at which the reference `ref` is referring to via function `proc`.\n`proc` receives a reference to this JSON value, allowing efficient, in place mutations without\nautomatically creating copies.\n\nThe second form of the `mutate` method provides specific functions `arrProc` for mutating arrays\nand `objProc` for mutating objects, again in a way in which no copies are created. For all\nother values, `proc` is being called.\n\n### JSON Patch\n\n_JSON Patch_ defines a JSON document structure for expressing a sequence of operations\nto apply to a JSON document. Each operation mutates parts of the JSON document. The supported\noperations specified by [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/) are\nimplemented by enum\n[`JSONPatchOperation`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPatch/JSONPatchOperation.swift):\n\n```swift\nenum JSONPatchOperation: Codable, Hashable, CustomStringConvertible, CustomDebugStringConvertible {\n  // add(path, value): Add `value` to the JSON value at `path`\n  case add(JSONPointer, JSON)\n  // remove(path): Remove the value at location `path` in a JSON value.\n  case remove(JSONPointer)\n  // replace(path, value): Replace the value at location `path` with `value`.\n  case replace(JSONPointer, JSON)\n  // move(path, from): Move the value at `from` to `path`. This is equivalent\n  // to first removing the value at `from` and then adding it to `path`.\n  case move(JSONPointer, JSONPointer)\n  // copy(path, from): Copy the value at `from` to `path`. This is equivalent\n  // to looking up the value at `from` and then adding it to `path`.\n  case copy(JSONPointer, JSONPointer)\n  // test(path, value): Compares value at `path` with `value` and fails if the\n  // two are different.\n  case test(JSONPointer, JSON)\n  ...\n}\n```\n\nStruct [`JSONPatch`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONPatch/JSONPatch.swift)\nbundles operations together into a \"patch object\" providing functionality to apply the patch to JSON values:\n\n```swift\nstruct JSONPatch: Codable, Hashable, CustomStringConvertible, CustomDebugStringConvertible {\n  // Sequence of operations.\n  let operations: [JSONPatchOperation]\n  // Initializer based on a sequence of operations\n  init(operations: [JSONPatchOperation]) { ... }\n  // Initializer based on a target and source JSON object\n  init(from: JSON, to: JSON, via maker: () -\u003e JSONPatchMaker = JSONPatchMaker.init)\n  // Decodes the provided data with the given decoding strategies.\n  init(data: Data,\n       dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,\n       floatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw,\n       userInfo: [CodingUserInfoKey : Any]? = nil) throws { ... }\n  // Decodes the provided string with the given decoding strategies.\n  init(string: String,\n       dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,\n       floatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw,\n       userInfo: [CodingUserInfoKey : Any]? = nil) throws { ... }\n  // Decodes the content at the provided URL with the given decoding strategies.\n  init(url: URL,\n       dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,\n       floatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw,\n       userInfo: [CodingUserInfoKey : Any]? = nil) throws { ... }\n  ...\n  // Applies this patch object to `json` mutating `json` in place.\n  func apply(to json: inout JSON) throws { ... }\n  ...\n}\n```\n\nThe following code shows how to load a JSON patch snippet into a patch object and\napply it to a json value:\n\n```swift\nlet jsonstr = \"\"\"\n  [\n    { \"op\": \"test\", \"path\": \"/a/b/c\", \"value\": \"foo\" },\n    { \"op\": \"remove\", \"path\": \"/a/b/c\" },\n    { \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] },\n    { \"op\": \"replace\", \"path\": \"/a/b/c\", \"value\": 42 },\n    { \"op\": \"move\", \"from\": \"/a/b/c\", \"path\": \"/a/b/d\" },\n    { \"op\": \"copy\", \"from\": \"/a/b/d\", \"path\": \"/a/b/e\" }\n  ]\n  \"\"\"\nlet patch = try JSONPatch(string: jsonstr)\nvar json: JSON = ...\ntry json.apply(patch: patch)\n```\n\nGiven two JSON values `source` and `target`, the expression `source.patch(to: target)` returns a `JSONPatch` object that when applied to `source`, transforms `source` into `target`. Function `patch` generates `JSONPatch` objects that perform the required transformation, but they are currently not optimized.\n\n## Merging JSON Values\n\n### Symmetrical Merge\n\nThe method **`isRefinement(of:)`** of enum `JSON` defines a relationship between\ntwo JSON values. `a.isRefinement(of: b)` is true if\n\n1. Both `a` and `b` are JSON values of the same type,\n2. If `a` and `b` are arrays, they have the same length _n_ and `a[i].isRefinement(of: b[i])`\n   holds for every i ∈ [0; _n_[,\n3. If `a` and `b` are objects, for every member `m` of `b` with value `b[m]`, there is a\n   member `m` of `a` with value `a[m]` such that `a[m].isRefinement(of: b[m])`,\n4. For all other types, `a` and `b` are the same, i.e. `a == b`.\n\nThis relationship intuitively models that whenever it's possible to read a value at a given\nlocation (or JSON pointer) from `b`, it's also possible to read a value at the same location from\n`a` and the value that is read for `a` is a refinement of the value read from `b`.\n\nThe following example is showcasing this relationship:\n\n```swift\nlet a = try JSON(string: #\"\"\"\n  {\n    \"a\": [1, { \"b\": 2 }],\n    \"c\": { \"d\": [{}] }\n  }\n\"\"\"#)\nlet b = try JSON(string: #\"\"\"\n  {\n    \"a\": [1, { \"b\": 2, \"e\": 4 }],\n    \"c\": { \"d\": [{\"f\": 5}] }\n  }\n\"\"\"#)\nb.isRefinement(of: a) ⇒ true\n```\n\nEnum `JSON` provides a method **`merging(value:)`** for merging two JSON values `a` and `b` such\nthat the result of the merge `a.merging(value: b)` is the \"smallest\" JSON value that is a refinement of both `a`\nand `b`. If such a merged value does not exist, then `merging(value:)` will return `nil`.\nHere is an example:\n\n```swift\nlet c = try JSON(string: #\"\"\"\n  { \"a\": [1, {\"e\": 8}],\n    \"c\": {\"f\": \"hello\"},\n    \"g\": 9 }\n\"\"\"#)\na.merging(value: c) \n⇒\n{\n  \"a\": [1, { \"b\": 2, \"e\": 8 }],\n  \"c\": { \"d\": [{}], \"f\": \"hello\" },\n  \"g\": 9\n}\n```\n\nIntuitively, `merging(value:)` combines two JSON values by adding all non-existing values to the\nmerged value and merging overlapping values when possible. Whenever it is not possible to merge\ntwo values, `merging(value:)` will fail by returning `nil`.\n\n### Overriding Merge\n\nAn alternative method, **`overriding(with:)`** merges two JSON values differently, letting the JSON\nvalue passed as an argument override values of the receiver whenever merging would fail otherwise.\nAs opposed to method `merging(value:)`, combining arrays does not require the arrays to\nbe of the same length. The resulting array has always the length of the longest of the two\narrays and individual elements are combined using `overriding(with:)` whenever two\nelements are available.\n\nHere is an example which would fail if `merging(value:)` would be used instead:\n\n```swift\nlet d = try JSON(string: #\"\"\"\n  {\n    \"a\": [1, { \"e\": 2 }, 3],\n    \"c\": { \"d\": \"hello\" },\n    \"f\": 5\n  }\n\"\"\"#)\na.overriding(with: d)\n⇒\n{\n  \"a\": [1, { \"b\": 2, \"e\": 2 }, 3],\n  \"c\": { \"d\": \"hello\" },\n  \"f\": 5\n}\n```\n\n### JSON Merge Patch\n\n_DynamicJSON_ provides basic support for _JSON Merge Patch_ as defined by\n[RFC 7396](https://datatracker.ietf.org/doc/html/rfc7396/).\n\nA JSON merge patch document describes changes to be made to a target JSON document using\na syntax that closely mimics the document being modified. Recipients of a merge patch\ndocument determine the exact set of changes being requested by comparing the content of the\nprovided patch against the current content of the target document. If the provided merge\npatch contains members that do not appear within the target, those members are added.\nIf the target does contain the member, the value is replaced. Null values in the merge\npatch are given special meaning to indicate the removal of existing values in the target.\n\nThe algorithm to apply a merge patch document to a JSON value is implemented by method\nthe **`merging(patch:)`** of enum\n[`JSON`](https://github.com/objecthub/swift-dynamicjson/blob/4719984b16dca8e60d9917fcebea5704f513b962/Sources/DynamicJSON/JSON.swift#L538).\n\n```swift\n// Merges this JSON value with the given JSON value `patch` recursively. Objects are\n// merged key by key with values from `patch` overriding values of the object represented\n// by this JSON value. All other types of JSON values are not merged and `patch` overrides\n// this JSON value.\nfunc merging(patch: JSON) -\u003e JSON { ... }\n```\n\nThe implementation for applying a merge patch document to a JSON value is not mutating\nan existing JSON value. It is constructing a new JSON value from scratch by merging\nthe old value with the merge patch document.\n\n## Validating JSON Data\n\n_DynamicJSON_ implements _JSON Schema_ as defined by the\n[2020-12 Internet Draft specification](https://datatracker.ietf.org/doc/draft-bhutton-json-schema/) for\nvalidating JSON data. The framework is flexible allowing extensions for future revisions.\n\n### Implementation Overview\n\nA JSON schema gets represented by enum [`JSONSchema`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchema.swift).\nIt is possible to load JSON schema values either from a file, decode them from a string,\nor from a data object. In the context of schema validation, top-level schema values are managed via class\n[`JSONSchemaResource`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaResource.swift)\nwhich pre-processes and validates schema values and provides an identity for them. Often it's easier to just work\nwith `JSONSchemaResource` objects directly. JSON schema are identified by\n[`JSONSchemaIdentifier`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaIdentifier.swift)\nvalues, which are essentially URIs with JSON schema-specific methods. A `JSONSchemaIdentifier`\nvalue is either absolute or relative and it is either a base URI, i.e. it is referring to a top-level schema,\nor it is a non-base URI and thus refers to a schema nested within another schema via a URI fragment.\n\nThe semantics of a schema is defined by their dialect. A schema dialect gets identified by a URI.\nA schema value provides access to their dialect identifier via property `schema`. If no identifier\nis provided, a default is assumed (which is `JSONSchemaDialect.draft2020` right now for top-level schema\nand the dialect of the enclosing schema for nested schema). Schema dialects are represented by\nimplementations of the\n[`JSONSchemaDialect`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaDialect.swift)\nprotocol. A key responsibility of `JSONSchemaDialect` implementations is to provide a factory method\n`validator(for:, in:)` for creating validator objects for this dialect. Validator objects implement protocol\n[`JSONSchemaValidator`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidator.swift)\nwhich provides one `validate()` method that takes a JSON instance and returns a\n[`JSONSchemaValidationResult`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift)\nvalue. This method gets eventually called to validate a JSON value.\n\nThe whole schema validation process gets initiated and controlled by a\n[`JSONSchemaRegistry`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaRegistry.swift)\nobject. JSON schema registries define:\n\n  - A set of supported dialects with their corresponding URI identities,\n  - A default dialect (for schema resources that do not define a dialect themselves),\n  - A set of known/loaded schema resources with their corresponding identities, and\n  - [`JSONSchemaProvider`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaProvider.swift)\n    objects, each implementing a method for discovering and loading new schema resources for\n    schema that are not loaded already.\n\nMost of the functionality of class\n[`JSONSchemaRegistry`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaRegistry.swift)\nis about configuring registry objects by registering supported dialects, inserting available\nschema resources and setting up schema providers for automatically discovering schema resources.\nOnce a registry is configured, method `validator(for:, dialect:)` can be called to obtain a\n[`JSONSchemaValidator`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidator.swift)\nobject for the given schema resource and default dialect. This validator object can then\nbe used to validate an arbitrary number of JSON instances.\n\nThe following example shows how validation is used in general:\n\n```swift\n// Create a new schema registry\nlet registry = JSONSchemaRegistry()\n// Register a schema resource from a string literal\ntry registry.register(resource: JSONSchemaResource(string: #\"\"\"\n  {\n    \"$id\": \"https://example.com/schema/test\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"prop1\": {\n        ...\n      }\n    }\n  }\n\"\"\"#))\n...\n// Load a schema resource from a file\ntry registry.loadSchema(from: URL(filePath: \"/Users/objecthub/foo.json\"))\n...\n// Make JSON schema stored in json files under the given directory discoverable\nregistry.register(provider:\n  StaticJSONSchemaFileProvider(\n    directory: URL(filePath: \"/Users/objecthub/myschema\"),\n    base: JSONSchemaIdentifier(string: \"http://example.com/schemas\")!))\n...\n// Obtain a validator for a schema\nguard let validator = try? registry.validator(for: \"https://example.com/schema/test\") else {\n  // Throw error stating that the schema could not be found\n}\n// Validate a JSON instance `json`\nlet result = validator.validate(json)\nprint(\"valid = \\(result.isValid)\")\n```\n\nSchema validators return\n[`JSONSchemaValidationResult`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift)\nvalues. These are containers which provide access to information collected during the\nvalidation process. `JSONSchemaValidationResult` values encapsulate the following information:\n\n  - Validation errors\n  - Format constraints (i.e. format requirements for string values defined by the `format` keyword)\n  - Meta tags (i.e. annotations about access and deprecations)\n  - Default values (i.e. default values defined by the `default` keyword)\n  \nFor figuring out whether validation was successful, it is sufficient to use property\n`isValid` of `JSONSchemaValidationResult`. It returns true if no validation errors were found.\nOtherwise, property `errors` provides access to the validation errors found. Other annotations\nthat are collected during validation are discussed [below](#metadata-and-defaults).\n\n### Validation API\n\nIf an application only validates JSON instances against a small number of fixed\nschema (e.g. provided statically at application startup), it would be overkill to make use\nof the low-level API introduced above. For such simple use cases, enum `JSON` provides the\nfollowing convenience methods:\n\n```swift\nenum JSON: Hashable, ... {\n  // Returns true if this JSON document is valid for the given JSON schema (using\n  // `registry` for resolving references to schema referred to from `schema`).\n  func valid(for schema: JSONSchema,\n             dialect: JSONSchemaDialect? = nil,\n             using registry: JSONSchemaRegistry? = nil) -\u003e Bool\n  \n  // Returns a schema validation result for this JSON document validated against the\n  // JSON schema `schema` (using`registry` for resolving references to schema\n  // referred to from `schema`).\n  func validate(with schema: JSONSchema,\n                dialect: JSONSchemaDialect? = nil,\n                using registry: JSONSchemaRegistry? = nil) throws -\u003e JSONSchemaValidationResult\n  \n  // Returns true if this JSON document is valid for the given JSON schema (using\n  // `registry` for resolving references to schema referred to from `schema`).\n  func valid(for resource: JSONSchemaResource,\n             dialect: JSONSchemaDialect? = nil,\n             using registry: JSONSchemaRegistry? = nil) -\u003e Bool\n  \n  // Returns a schema validation result for this JSON document validated against the\n  // JSON schema `schema` (using`registry` for resolving references to schema\n  // referred to from `schema`).\n  func validate(with resource: JSONSchemaResource,\n                dialect: JSONSchemaDialect? = nil,\n                using registry: JSONSchemaRegistry? = nil) throws  -\u003e JSONSchemaValidationResult\n  ...\n}\n```\n\nThese validation methods are creating new registries on demand if parameter `registry` is\nset to `nil`, with only the provided schema or schema resource getting registered. For using\nnon self-contained schema, it is therefore necessary to set up a suitable registry first and\npass it in via the `registry` parameter. Alternatively, it is possible to use the default\nregistry `JSONSchemaRegistry.default` if a single, shared, global registry is sufficient.\n\n### Metadata and Defaults\n\n#### Format annotations\n\n`format` annotations of a JSON schema, i.e. declarations that JSON string values have a particular\nformat, are being collected and made available via the\n[`formatConstraints`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift#L123C27-L123C44)\nproperty of\n[`JSONSchemaValidationResult`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift)\nvalues. Each constraint is an instance of\n[`Annotation\u003cFormatConstraint\u003e`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift#L40) providing access to fields `value` (a `LocatedJSON` value), `location` (within the schema), `message.format`\nand `message.valid`, with `message.valid` being a value of type `Bool?`. `true` refers to valid\nconstraints, `false` to invalid constraints, and `nil` to constraints that could not be validated.\nHere is code that prints out all invalid constraints:\n\n```swift\nval res: JSONSchemaValidationResult = ...\nfor constraint in res.formatConstraints where constraint.message.valid == false {\n  print(\"value \\(constraint.value) does not match format '\\(constraint.message.format)'\")\n}\n```\n\nIf invalid format constraints should result in a validation error, the vocabulary\n`https://json-schema.org/draft/2020-12/meta/format-annotation` needs to be enabled.\nThis can be done by creating a custom\n[`JSONSchemaDraft2020.Dialect`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaDraft2020.swift#L72C17-L72C24)\nvalue with a vocabulary of type\n[`JSONSchemaDraft2020.Vocabulary`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaDraft2020.swift#L39)\nwhose `format` property is set to true. Since such a dialect is useful frequently, a preconfigured\ndialect value is available via\n[`JSONSchemaDialect.draft2020Format`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaDialect.swift#L41).\nDefining a registry with this dialect as its default will always also validate format annotations.\n\n#### Default annotations\n\n`default` annotations of a JSON schema, i.e. declarations that properties have a given default\nvalue if the property is not defined explicitly, are being collected and made available via the\n[`defaults`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift#L129)\nproperty of\n[`JSONSchemaValidationResult`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift)\nvalues. `defaults` is providing a map from `JSONLocation` values to tuples `(exists: Bool, values: Set\u003cJSON\u003e)`.\nThe `exists` component of the tuple states whether a value exists at this location (and thus, not default needs to be injected).\nThe `values` component provides a set of JSON values which are all suitable as defaults (a schema can define multiple,\nalternative defaults). Here is code that prints out default values computed during a validation process:\n\n```swift\nlet schema = try JSONSchema(string: #\"\"\"\n  {\n    \"$id\": \"https://objecthub.com/example/person\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"title\": \"person\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"name\": {\n        \"type\": \"string\",\n        \"minLength\": 1\n      },\n      \"birthday\": {\n        \"type\": \"string\",\n        \"format\": \"date\"\n      },\n      \"numChildren\": {\n        \"type\": \"integer\",\n        \"default\": 0\n      },\n      \"address\": {\n        \"oneOf\": [\n          { \"type\": \"string\", \"default\": \"12345 Mcity\" },\n          { \"$ref\": \"#address\",\n            \"default\": { \"city\": \"Mcity\", \"postalCode\": \"12345\" } }\n        ]\n      },\n      \"email\": {\n        \"type\": \"array\",\n        \"maxItems\": 3,\n        \"items\": {\n          \"type\": \"string\",\n          \"format\": \"email\"\n        }\n      }\n    },\n    \"required\": [\"name\", \"birthday\"],\n    \"$defs\": {\n      \"address\": {\n        \"$anchor\": \"address\",\n        \"type\": \"object\",\n        \"properties\": {\n          \"street\": {\n            \"type\": \"string\"\n          },\n          \"city\": {\n            \"type\": \"string\"\n          },\n          \"postalCode\": {\n            \"type\": \"string\",\n            \"pattern\": \"\\\\d{5}\"\n          }\n        },\n        \"required\": [\"city\", \"postalCode\"]\n      }\n    }\n  }\n\"\"\"#)\n/// `instance0` is a valid instance of `schema`\nlet instance0: JSON = [\n  \"name\": \"John Doe\",\n  \"birthday\": \"1983-03-19\",\n  \"numChildren\": 2,\n  \"email\": [\"john@doe.com\", \"john.doe@gmail.com\"]\n]\ninstance0.valid(for: schema) ⇒ true\n/// `instance1` is not a valid instance of `schema`\nlet instance1: JSON = [\n  \"name\": \"John Doe\",\n  \"email\": [\"john@doe.com\", \"john.doe@gmail.com\"]\n]\ninstance1.valid(for: schema) ⇒ false\n/// `instance2` is a valid instance of `schema`\nlet instance2: JSON = [\n  \"name\": \"John Doe\",\n  \"birthday\": \"1983-03-19\",\n  \"address\": \"12 Main Street, 17445 Noname\"\n]\nlet res2 = try instance2.validate(with: schema)\nres2.isValid ⇒ true\nfor (location, (exists, values)) in res2.defaults {\n  if exists {\n    print(\"\\(location) exists; defaults: \\(values)\")\n  } else {\n    print(\"\\(location) does not exist; defaults: \\(values)\")\n  }\n}\n```\n\nThe loop at the end of this code prints out the following text:\n\n```\n$['numChildren'] does not exist; defaults: [0]\n$['address'] exists; defaults: [\n  \"12345 Mcity\",\n  {\n    \"postalCode\" : \"12345\",\n    \"city\" : \"Mcity\"\n  }\n]\n```\n\n#### Property metadata\n\nProperty metadata annotations of a JSON schema such as `deprecated`, `readOnly`, and `writeOnly`,\nare being collected and made available via the\n[`tags`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift#L118C27-L118C31)\nproperty of\n[`JSONSchemaValidationResult`](https://github.com/objecthub/swift-dynamicjson/blob/main/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift)\nvalues. Each location within the validated value with a metadata annotation is included in this array\nwith an entry of type\n[`Annotation\u003cMetaTags\u003e`](https://github.com/objecthub/swift-dynamicjson/blob/344527ee09e7829dce4e4505b3c834be2ab0e977/Sources/DynamicJSON/JSONSchema/JSONSchemaValidationResult.swift#L40) providing access to fields `value` (a `LocatedJSON` value), `location` (within the schema), `message.deprecated`\n`message.readOnly`, and `message.writeOnly`. `deprecated`, `readOnly`, and `writeOnly` are boolean properties.\n\n## Requirements\n\nThe following technologies are needed to build the _DynamicJSON_ framework. The library\nand the command-line tool can both be built either using _Xcode_ or the _Swift Package Manager_.\n\n- [Xcode 16](https://developer.apple.com/xcode/)\n- [Swift 6](https://developer.apple.com/swift/)\n- [Swift Package Manager](https://swift.org/package-manager/)\n\n## Copyright\n\nAuthor: Matthias Zenger (\u003cmatthias@objecthub.com\u003e)  \nCopyright © 2024-2025 Matthias Zenger. All rights reserved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobjecthub%2Fswift-dynamicjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobjecthub%2Fswift-dynamicjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobjecthub%2Fswift-dynamicjson/lists"}