Skip to content
Kavachकवच

JSON: Nested data

● Intermediate3 min

Objects inside objects and lists inside them: chain reads to go down, or decode the whole shape into records inside records.

use std.json

fn main() ! Error {
    const text = """
        \{
            "order": \{
                "id": 7,
                "customer": \{ "name": "Asha", "city": "Pune" },
                "items": [
                    \{ "name": "pen", "price": 20 },
                    \{ "name": "ink", "price": 45 }
                ]
            }
        }
        """
    const doc = try json.parse(text)
    const order = doc["order"]
    print(order["customer"]["name"].text() ?? "")
    print(order["items"][1]["price"].int() ?? 0)
    let total = 0
    for item in order["items"].list() ?? [] {
        total += item["price"].int() ?? 0
    }
    print("{order["items"].len()} items, {total} in all")
    print(order["customer"]["phone"]["mobile"].text() ?? "no phone")
}

The program ran and printed:

kavach run nested.kav

Asha452 items, 65 in allno phone
nested.kav: Kavach code, then what running it prints
  • order["items"][1]["price"] goes down one level at a time: a key for an object, a position for an array.
  • .list() gives an array's items, to loop over.
  • A path that isn't there, however deep, ends in Null: no phone.

When you know the shape, write it as types, and one call reads it all, checked at every level:

use std.json

type Customer {
    name: String
    city: String
}

type Item {
    name: String
    price: Int
}

type Order {
    id: Int
    customer: Customer
    items: [Item]
}

fn main() ! Error {
    const text = """
        \{ "id": 7, "customer": \{ "name": "Asha", "city": "Pune" },
          "items": [ \{ "name": "pen", "price": 20 }, \{ "name": "ink", "price": 45 } ] }
        """
    const order = try json.decode<Order>(text)
    print(order.customer.city)
    print(order.items.map(i => i.name))
    print(order.items.sum(i => i.price))
}

The program ran and printed:

kavach run nested-decode.kav

Pune["pen", "ink"]65
nested-decode.kav: Kavach code, then what running it prints