Month DD, 2026
bdljsn::Json Enchancements
Since Introducing bdljsn::Json many features have been added that make use of that component easier and more effective. The purpose of this article is summarize these features for our users.
Added Conversions and Fluent Operators
Recently added methods and implicit conversions allow users to compose
and operate on Json objects with less code clutter.
Additionally, many manipulator methods that had previously
returned void now return an reference to the object (a.k.a., a “fluent”
method). Successive invocations of these manipulators can now be combined
into a single expression.
Consider the assembly of an array-type Json object. Previously that would might look like this:
Json json; // Create the `Json` object.
json.makeArray(); // Make it an array type.
json.theArray().pushBack(Json(42)); // Must access via `theArray`.
json.theArray().pushBack(Json("string")); // `pushBack` `Json` objects.
json.theArray().pushBack(Json(false)); // " "
json.theArray().pushBack(Json(JsonObject())); // " "
json.theArray().pushBack(Json(JsonNull())); // " "
assert(json[0] == Json(42)); // Must compare `Json` objects.
assert(json[1] == Json("string")); // " "
assert(json[2] == Json(false)); // " "
assert(json[3] == Json(JsonObject())); // " "
assert(json[4] == Json(JsonNull())); // " "
Now, the same code can be written more concisely:
Json json; // Create the (null) `Json` object.
json.pushBack(42) // We need not invoke `makeArray`
.pushBack("string") // We need not invoke `theArray`.
.pushBack(false) // Pushed values need not be `Json` objects.
.pushBack(JsonObject()) // `pushBack` is "fluent" -- need not repeat
.pushBack(JsonNull()); // the `json` variable name.
assert(json[0] == 42); // Can compare `Json` objects
assert(json[1] == "string"); // to non-`Json` values.
assert(json[2] == false);
assert(json[3] == JsonObject());
assert(json[4] == jsonNull); // Note: Use `JsonNull` constant.
Notice that the Json class now has many methods that mirror methods of
of JsonArray (e.g., pushBack) so array operations can be performed
directly on the Json object without using the theArray() method that
was previously required. Moreover, when array operations are applied to
a Json object having type JsonNull, that object’s type is implicitly
converted to JsonArray.
Similarly, many of the methods of JsonObject have also been “imported” to
Json and they too implicitly change a Json object’s type from
JsonNull to JsonObject.
The bdljsn::jsonNull Constant
Notice in the final line of the previous example that
bdljsn_jsonnull
now defines, bdljsn::jsonNull (leading lower case j),
a constant having the singular value of the bdljsn::JsonNull class.
Initializer List Enhancements
For some time, the bdljsn::JsonArray and bdljsn::JsonObect and classes
have provided constuctors and maniuplator
methods that accept std::initializer_list class templates. Thus, users
have been able to define those objects using braced lists of Json
objects to define JsonArray objects and braced lists of key/Json
objects to to define JsonObject objects. For example:
JsonArray array0 { // A list of `Json` objects
Json(123),
Json("string"),
Json(true),
Json(JsonObject())
};
JsonObject object0 { // A mapping from key values to `Json` objects.
{ "play", Json("Waiting for Godot") },
{ "characters", Json(JsonArray {
Json("Didi"),
Json("Gogo"),
Json("Pozzo"),
Json("Lucky")}
)
}
};
More recently, the implementation has been generalized so those braced lists
consist of a wide assortment type suitable for constructing Json objects.
Thus, the previous example can now be written more concisely (and more
readably):
JsonArray array1 { // The list elements need no longer be `Json` objects.
123,
"string",
true,
JsonObject { }
};
JsonObject object1 { // The values need no longer be `Json` objects.
{ "play", "Waiting for Godot" },
{ "characters", JsonArray {
"Didi",
"Gogo",
"Pozzo",
"Lucky" }
}
};
assert( array0 == array1);
assert(object0 == object1);
The types accepted in braced lists include:
boolintegral types
float
double
bdldfp::Decimal64
const char *
const bsl::string&
const std::string&
const std::pmr::string&(where available)
const bsl::string_view&
const std::string_view&(where distinct frombsl::string_view)
JsonNull
JsonNumber
JsonArray
JsonObject
Json
Finally, the bdljsn::Json class itself did not and still does not
directly support initializer lists:
Json jx = { {"a", 1}, {"b", 2} }; // Error. No such CTOR.
// Note: User intent is ambiguous.
// * Object having two members, or
// * Array having two elements, each
// an array of two elements?
To disambiguate intent when creating a Json object from an
std::initializer_list, qualify the statement by supplying the
JsonArray/JsonObject types explicitly.
Json ja = JsonArray { {"a", 1}, {"b", 2} };
assert(true == ja.isArray());
assert(2 == ja.size());
assert(true == ja[0].isArray());
assert(true == ja[1].isArray());
Json jo = JsonObject{ {"a", 1}, {"b", 2} };
assert(true == jo.isObject());
assert(2 == jo.size());
assert(true == jo.contains("a"));
assert(1 == jo["a"]);
assert(true == jo.contains("b"));
assert(2 == jo["b"]);
The visit Method
The bdljsn::Json class now has the (overloaded) visit method which
supports the “visitor” pattern. In this pattern, a user-supplied, type-based
functor is invoked for each of the nodes of a JSON document.
See bdljsn_json Example 3: Using the visit Method to Traverse a Json Object.