djson v3.1.3
JSON parser
 
Loading...
Searching...
No Matches
Documentation

Features

  • JSONC parse mode
  • Copiable Json objects
  • Default construction (representing null) is "free"
  • as_string_view()
  • Heterogenous arrays
  • Escaped text
  • Implicit construction for nulls, booleans, numbers, strings
  • Serialization, pretty-print (default)
  • Customization points for from_json and to_json
  • Build tree from scratch

Limitations

  • Escaped unicode (eg \u1F604) not currently supported

Usage

JSONC

dj::ParseMode controls whether JSONC features are accepted or rejected during parsing:

  • Single-line comments: //
  • Multi-line comments: /* ... */
  • Trailing commans: [1,2,]

There are three parse modes available:

dj::ParseMode::Auto looks for a mode line at the start of the string, per the spec:

// -*- mode: jsonc -*-

Or

// -*- jsonc -*-

If found, the mode is set to Jsonc, else Strict.

dj::Json::parse() and dj::Json::from_file() accept a dj::ParseMode parameter, defaulted to dj::ParseMode::Auto.

Input

dj::Json is the primary type around which the entire library's interface is designed. Use the static member function dj::Json::parse() to attempt to parse text into a Json value. It returns a dj::Result (ie, std::expected<Json, Error>):

constexpr auto text = R"({
"elements": [-2.5e3, "bar"],
"foo": "party",
"universe": 42
})";
auto result = dj::Json::parse(text);
auto& json = result.value();
assert(!json.is_null());
static auto parse(std::string_view text, ParseMode mode=ParseMode::Auto) -> Result
Parse JSON text.

Access values of Objects via dj::Json::operator[](std::string_view). A const Json will return null for non-existent keys, whereas a mutable Json will return a reference to a newly created value:

auto const& elements = json["elements"];
auto const& foo = json["foo"];
auto const& universe = json["universe"];
assert(std::as_const(json)["nonexistent"].is_null());

Access values of Arrays via dj::Json::operator[](std::size_t). A const Json will return null for out-of-bound indices, whereas a mutable Json will resize itself and return a reference to a newly created value:

auto const& elem0 = elements[0];
auto const& elem1 = elements[1];
assert(elements[2].is_null());

Check the type of a Json value via dj::Json::get_type() / dj::Json::is_*():

assert(elements.get_type() == dj::JsonType::Array);
assert(elem0.get_type() == dj::JsonType::Number);
assert(elem1.is_string());
assert(foo.is_string());
assert(universe.is_number());

Convert to a C++ type via dj::Json::as*():

assert(elem0.as_double() == -2500.0); // == on floats is just for exposition.
assert(elem1.as_string_view() == "bar");
assert(foo.as_string_view() == "party");
assert(universe.as<int>() == 42);

Iterate over Arrays via dj::Json::as_array(). Array elements are ordered:

for (auto const [index, value] :
std::views::enumerate(elements.as_array())) {
std::println("[{}]: {}", index, value);
}
// output:
// [0]: -2500
// [1]: "bar"

Iterate over Objects via dj::Json::as_object(). Object elements are not ordered:

for (auto const& [key, value] : json.as_object()) {
std::println(R"("{}": {})", key, value);
}
// output (unordered):
// "universe": 42
// "foo": "party"
// "elements": [-2500,"bar"]

Output

Use dj::Json::set*() to overwrite the value of a Json with a literal (null / boolean / number / string), an empty Array / Object, or another Json value. It can also be constructed this way:

auto json = dj::Json{};
assert(json.is_null());
json.set_number(42);
assert(json.as<int>() == 42);
json.set_object();
assert(json.is_object());
assert(json.as_object().empty());
json.set_value(dj::Json::empty_array());
assert(json.is_array());
assert(json.as_array().empty());
json.set_value(dj::Json{true});
assert(json.as_bool());
Library interface, represents a valid JSON value.
Definition json.hpp:77
static auto empty_array() -> Json const &
Obtain a Json representing an empty Array value.

Serialization

Serialize to strings via dj::Json::serialize() or dj::to_string() or std::format() (and related). The first two can be customized via dj::SerializeOptions. std::formatter<Json> uses SerializeFlag::NoSpaces for compact output.

auto json = dj::Json::parse(R"({"foo": 42, "bar": [-5, true]})").value();
auto const options = dj::SerializeOptions{
.indent = "\t",
.newline = "\n",
};
auto const serialized = json.serialize(options);
std::print("{}", serialized);
/* output:
{
"bar": [
-5,
true
],
"foo": 42
}
*/
@ TrailingNewline
Append newline at the end. Ignored if NoSpaces is set.
Definition json.hpp:43
@ SortKeys
Sort keys lexicographically.
Definition json.hpp:41
Serialization options.
Definition json.hpp:53
std::string_view indent
Indentation string. Ignored if SerializeFlag::NoSpaces is set.
Definition json.hpp:55

Read from / write to files via dj::Json::from_file() / dj::Json::to_file().

Customization

Parse your own types:

namespace foo {
struct Item {
std::string name{};
int weight{};
auto operator==(Item const&) const -> bool = default;
};
void from_json(dj::Json const& json, Item& out) {
from_json(json["name"], out.name);
from_json(json["weight"], out.weight);
}
void to_json(dj::Json& out, Item const& item) {
to_json(out["name"], item.name);
to_json(out["weight"], item.weight);
}
} // namespace foo
auto const src = foo::Item{
.name = "Orb",
.weight = 5,
};
auto json = dj::Json{};
to_json(json, src);
auto dst = foo::Item{};
from_json(json, dst);
assert(src == dst);
void from_json(Json const &json, Type &value, Type const fallback={})
Assign JSON as value.
Definition json.hpp:260
void to_json(Json &json, Type const &value)
Assign value to JSON.
Definition json.hpp:266