JSON

CloneableJSON Documentation

The CloneableJSON struct provides a flexible way to work with JSON-like data structures in Swift, allowing for schema validation and easy manipulation of nested data. This documentation will focus on using CloneableJSON with the provided schema for a measure pole task list.

JSON Schema Guide

Schema Guide

Schema

The schema we'll be working with is as follows:

{
  "measure_pole_task_list": {
    "type": "array",
    "description": "Array of tasks associated with the pole",
    "array_type": "object",
    "properties": {
      "id": {
        "type": "string",
        "description": "Id of the task or attachment"
      },
      "name": {
        "type": "string",
        "description": "Name of the task to be performed on the pole"
      },
      "inspection_phase": {
        "type": "string",
        "description": "Phase of the inspection this task will be presented. ar or photo"
      },
      "design_height": {
        "type": "number",
        "description": "Expected height for the task in meters"
      },
      "actual_height": {
        "type": "number",
        "description": "The actual measured height in meters"
      },
      "status": {
        "type": "string",
        "description": "Status of the item"
      }
    }
  }
}

Creating a CloneableJSON instance

To create a CloneableJSON instance with this schema:

let schema = """
{
  "measure_pole_task_list": {
    "type": "array",
    "description": "Array of tasks associated with the pole",
    "array_type": "object",
    "properties": {
      "id": {
        "type": "string",
        "description": "Id of the task or attachment"
      },
      "name": {
        "type": "string",
        "description": "Name of the task to be performed on the pole"
      },
      "inspection_phase": {
        "type": "string",
        "description": "Phase of the inspection this task will be presented. ar or photo"
      },
      "design_height": {
        "type": "number",
        "description": "Expected height for the task in meters"
      },
      "actual_height": {
        "type": "number",
        "description": "The actual measured height in meters"
      },
      "status": {
        "type": "string",
        "description": "Status of the item"
      }
    }
  }
}
"""

do {
    let cloneableJSON = try CloneableJSON(schema: schema)
    print("CloneableJSON instance created successfully")
} catch {
    print("Error creating CloneableJSON: \(error)")
}

Working with CloneableJSON

Creating the Measure Pole Task List

To create the measure pole task list according to the schema:

let cloneableJSON = try CloneableJSON(schema: schema)

// Initialize the measure_pole_task_list as an empty array
cloneableJSON.value = .object(["measure_pole_task_list": .array([])])

// Create a task
let task: [String: CloneableJSONValue] = [
    "id": .value(AnyCloneableData(data: CloneableString("task1"))),
    "name": .value(AnyCloneableData(data: CloneableString("Measure pole height"))),
    "inspection_phase": .value(AnyCloneableData(data: CloneableString("ar"))),
    "design_height": .value(AnyCloneableData(data: CloneableNumber(10.5))),
    "actual_height": .value(AnyCloneableData(data: CloneableNumber(10.2))),
    "status": .value(AnyCloneableData(data: CloneableString("completed")))
]

// Add the task to the measure_pole_task_list
if case .object(var rootObject) = cloneableJSON.value,
   case .array(var taskList) = rootObject["measure_pole_task_list"] {
    taskList.append(.object(task))
    rootObject["measure_pole_task_list"] = .array(taskList)
    cloneableJSON.value = .object(rootObject)
}

Adding Multiple Tasks

To add multiple tasks:

let tasks: [[String: CloneableJSONValue]] = [
    [
        "id": .value(AnyCloneableData(data: CloneableString("task1"))),
        "name": .value(AnyCloneableData(data: CloneableString("Measure pole height"))),
        "inspection_phase": .value(AnyCloneableData(data: CloneableString("ar"))),
        "design_height": .value(AnyCloneableData(data: CloneableNumber(10.5))),
        "actual_height": .value(AnyCloneableData(data: CloneableNumber(10.2))),
        "status": .value(AnyCloneableData(data: CloneableString("completed")))
    ],
    [
        "id": .value(AnyCloneableData(data: CloneableString("task2"))),
        "name": .value(AnyCloneableData(data: CloneableString("Check pole condition"))),
        "inspection_phase": .value(AnyCloneableData(data: CloneableString("photo"))),
        "design_height": .value(AnyCloneableData(data: CloneableNumber(5.0))),
        "actual_height": .value(AnyCloneableData(data: CloneableNumber(5.1))),
        "status": .value(AnyCloneableData(data: CloneableString("in_progress")))
    ]
]

if case .object(var rootObject) = cloneableJSON.value,
   case .array(var taskList) = rootObject["measure_pole_task_list"] {
    for task in tasks {
        taskList.append(.object(task))
    }
    rootObject["measure_pole_task_list"] = .array(taskList)
    cloneableJSON.value = .object(rootObject)
}

Accessing and Modifying Data

To access and modify data in the CloneableJSON structure:

// Accessing data
if case .object(let rootObject) = cloneableJSON.value,
   case .array(let tasks) = rootObject["measure_pole_task_list"] {
    for task in tasks {
        if case .object(let taskData) = task,
           case .value(let nameData) = taskData["name"],
           let name = nameData.data as? CloneableString {
            print("Task name: \(name.value)")
        }
    }
}

// Modifying data
if case .object(var rootObject) = cloneableJSON.value,
   case .array(var tasks) = rootObject["measure_pole_task_list"] {
    if case .object(var firstTask) = tasks[0] {
        firstTask["status"] = .value(AnyCloneableData(data: CloneableString("completed")))
        tasks[0] = .object(firstTask)
    }
    rootObject["measure_pole_task_list"] = .array(tasks)
    cloneableJSON.value = .object(rootObject)
}

Validating the Data

To validate the data against the schema:

if cloneableJSON.validate() {
    print("Data is valid according to the schema")
} else {
    print("Data does not match the schema")
}

Best Practices

  1. Always use the appropriate CloneableDataType for each field (CloneableString for strings, CloneableNumber for numbers).

  2. Validate the data against the schema after making changes to ensure consistency.

  3. Use optional binding and type checking when accessing data to handle potential mismatches safely.

  4. When modifying nested structures, make sure to reassign the modified value at each level of the hierarchy.

  5. Use descriptive variable names that match the schema structure for clarity.

By following these guidelines and examples, you can effectively use the CloneableJSON struct to work with the measure pole task list data structure in a type-safe and schema-validated manner.

Last updated