Skip to content

Conversation

@mattt
Copy link
Owner

@mattt mattt commented Jun 14, 2025

Resolves #11

The changes in #9 attempted to provide a stable ordering of JSON Schema properties using OrderedDictionary from apple/swift-collections. However, that type encodes as a JSON array instead of a JSON object, resulting in invalid JSON Schema documents.

This PR resolves this regression and adds new affordances in support of preserving order:

  • 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.

Example Usage

let json = """
{
  "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
if let propertyOrder = JSONSchema.extractSchemaPropertyOrder(from: jsonData) {
    // Configure decoder to preserve order
    let decoder = JSONDecoder()
    decoder.userInfo[JSONSchema.propertyOrderUserInfoKey] = propertyOrder

    // Decode with preserved property order
    let schema = 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
let nestedJSONData = """
{
  "definitions": {
    "person": {
      "firstName": "John",
      "lastName": "Doe"
    }
  }
}
""".data(using: .utf8)!

let keyOrder = JSONSchema.extractPropertyOrder(from: nestedJSONData, 
                                               at: ["definitions", "person"]) 
// keyOrder will be ["firstName", "lastName"]

@mattt mattt merged commit 51d27c2 into main Jun 14, 2025
1 check passed
@mattt mattt deleted the mattt/fix-ordered-dictionary-encoding branch June 14, 2025 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dictionaries are now encoded as Arrays.

2 participants