| Home | Libraries | People | FAQ | More

### Initializer Lists

Initializer lists can be used to construct or assign a `value`:

    value jv = {
        { "name", "John Doe" },
        { "active", true },
        { "associated-accounts", nullptr },
        { "total-balance", 330.00 },
        { "account-balances", { 84, 120, 126 } } };

Simple initializer lists produce an `array`:

    value jv = { true, 2, "hello", nullptr };

    assert( jv.is_array() );

    assert( jv.as_array().size() == 4 );

    assert( serialize(jv) == R"([true,2,"hello",null])" );

Initializer lists can be nested. Here we construct an array as an element of an array:

    value jv = { true, 2, "hello", { "bye", nullptr, false } };

    assert( jv.is_array() );

    assert( jv.as_array().back().is_array() );

    assert( serialize(jv) == R"([true,2,"hello",["bye",null,false]])" );

When a two element initializer list is nested within an enclosing initializer list, it is unclear whether it represents an `array` or an `object`:

    // Should this be an array or an object?
    value jv = { { "hello", 42 }, { "world", 43 } };

In such cases, if every element consists of a string followed by a single value, then the enclosing initializer list is interpreted as an `object`. Otherwise, it is interpreted as an `array`.

    value jv1 = { { "hello", 42 }, { "world", 43 } };

    assert( jv1.is_object() );

    assert( jv1.as_object().size() == 2 );

    assert( serialize(jv1) == R"({"hello":42,"world":43})" );

    // All of the following are arrays

    value jv2 = { { "make", "Tesla" }, { "model", 3 }, "black" };

    value jv3 = { { "library", "JSON" }, { "Boost", "C++", "Fast", "JSON" } };

    value jv4 = { { "color", "blue" }, { 1, "red" } };

    assert( jv2.is_array() && jv3.is_array() && jv4.is_array() );

To resolve the ambiguity manually, use an explicit constructor:

    value jv = { { "hello", 42 }, array{ "world", 43 } };

    assert( jv.is_array() );

    array& ja = jv.as_array();

    assert( ja[0].is_array() && ja[1].is_array());

    assert ( serialize(jv) == R"([["hello",42],["world",43]])" );

Initializer lists can be used to unambiguously construct or assign an `object` or `array`:

    value jv = { { "mercury", 36 }, { "venus", 67 }, { "earth", 93 } };

    assert( jv.is_object() );

    assert( serialize(jv) == R"({"mercury":36,"venus":67,"earth":93})" );

    array ja = { { "mercury", 36 }, { "venus", 67 }, { "earth", 93 } };

    assert( serialize(ja) == R"([["mercury",36],["venus",67],["earth",93]])" );

Similarly, an initializer list for an `object` is always interpreted as an `object`. In such cases, the initializer list must be a list of key-value pairs. For example, the following code will not compile because `1` is not convertible to a string:

    object jo = { { 1, 0.39 }, { "venus", 0.72 }, { "earth", 1 } };

The requirement for an initializer list to be interpreted as an `object` or `array` when initializing such an entity only applies to the outermost initializer list; subsequent nested elements will follow the usual ambiguity resolution rules.

    object jo = { { "mercury", { { "distance", 36 } } }, { "venus", { 67, "million miles" } }, { "earth", 93 } };

    assert( jo["mercury"].is_object() );

    assert( jo["venus"].is_array() );

Elements that are rvalues will be moved upon initialization:

    object jo1 = { { "john", 100 }, { "dave", 500 }, { "joe", 300 } };

    value jv = { { "clients", std::move(jo1) } };

    object& jo2 = jv.as_object()["clients"].as_object();

    assert( ! jo2.empty() && jo1.empty() );

    assert( serialize(jv) == R"({"clients":{"john":100,"dave":500,"joe":300}})" );

| Warning
Do not create variables of type `std::initializer_list`. This may result in temporaries being destroyed before the initializer list is used.

In all cases, the `storage_ptr` owned by an `object`, `array`, or `value` constructed from an initializer list will be propagated to each element, recursively.