Search code examples
arraysjsonyamlassociative-array

Why doesn't JSON have associative arrays?


Why doesn't JSON have associative arrays? YAML does.

You can't do this in JSON:

{
    productsBySku: [
        12J432: {
            price: 49.99,
            qty_in_stock: 4
        },
        5X4352: {
            price: 29.99,
            qty_in_stock: 5
        }
    ]
}

But in YAML you can do:

productsBySku:
  - 12J432: 
        price: 49.99,
        qty_in_stock: 4
  - 5X4352:
        price: 29.99,
        qty_in_stock: 5

I'm wondering on a technical level why this decision might have been made for JSON.


Solution

  • Why doesn't JSON have associative arrays?

    JSON doesn't have associative arrays in the PHP sense (e.g., ordered maps), but it certainly has key/value maps. They're called "objects."

    I'm wondering on a technical level why this decision might have been made for JSON.

    Crockford designed JSON to be a subset of JavaScript's object initialiser syntax. JavaScript didn't have associative arrays (in the ordered map sense) at the time, and so JSON doesn't. (Years afterward, JavaScript's standard library gained a Map object which is somewhat like an associative array in that its entries are iterated in insertion order, but they don't have a literal form.)

    YAML does

    Does it? I'm not seeing them, and Biffen seems to suggest otherwise.

    Reading the YAML spec, your YAML is exactly equivalent to this JSON (an array of objects, each with a single key referring to a subordinate object):

    {
        "productsBySku": [
            {
                "12J432": {
                    "price": 49.99,
                    "qty_in_stock": 4
                }
            },
            {
                "5X4352": {
                    "price": 29.99,
                    "qty_in_stock": 5
                }
            }
        ]
    }
    

    Even if YAML did have them, YAML ain't JSON1. ;-) They're different data notations, with different design goals. XML has namespaces, which JSON also doesn't have. YAML supports reusing nodes by reference, which allows for cyclical structures, which JSON doesn't.

    You can't do this in JSON

    It depends on what you're trying to do. Again, as far as I can tell, your YAML is exactly the same as the JSON above.

    If your goal is to have that list of products by SKU, you can:

    {
        "productsBySku": {
            "12J432": {
                "price": 49.99,
                "qty_in_stock": 4
            },
            "5X4352": {
                "price": 29.99,
                "qty_in_stock": 5
            }
        }
    }
    

    The productsBySku property is an object. Its properties are not ordered, so it's not an ordered map, but it is a map. If you needed the properties within it to have order, you'd have to add a property to them indicating what the order was, and then apply that order after deserializing.

    Alternately, you can use an array and then build your map after deserializing:

    {
        "productsBySku": [
            {
                "sku": "12J432",
                "price": 49.99,
                "qty_in_stock": 4
            },
            {
                "sku": "5X4352",
                "price": 29.99,
                "qty_in_stock": 5
            }
        ]
    }
    

    1 For those who don't know, YAML stands for "YAML Ain't Markup Language."