Merge branch 'json-view/12-view-values' into json-view/13-view-dump

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-10-02 11:43:33 +02:00
301 changed files with 5549 additions and 702 deletions
@@ -0,0 +1,15 @@
#include <iostream>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// a buffer containing a JSON text followed by more data
std::vector<std::uint8_t> input = {'[', '1', ',', '2', ',', '3', ']', 'o', 't', 'h', 'e', 'r'};
std::cout << std::boolalpha
<< json::accept(input.begin(), input.begin() + 7) << ' '
<< json::accept(input.begin(), input.end()) << '\n';
}
@@ -0,0 +1 @@
true false
@@ -0,0 +1,22 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json;
int main()
{
// create an ordered_json value; insertion order is preserved
ordered_json oj = {{"c", 3}, {"a", 1}, {"b", 2}};
// convert to json -- overload (4) is used; keys end up sorted
json j(oj);
// convert back to ordered_json -- the original insertion order is lost,
// because it was already given up when converting to json
ordered_json oj2(j);
std::cout << oj << '\n';
std::cout << j << '\n';
std::cout << oj2 << '\n';
}
@@ -0,0 +1,3 @@
{"c":3,"a":1,"b":2}
{"a":1,"b":2,"c":3}
{"a":1,"b":2,"c":3}
@@ -44,7 +44,7 @@ int main()
// create an object from std::unordered_multimap
std::unordered_multimap<std::string, bool> c_ummap
{
{"one", true}, {"two", true}, {"three", false}, {"three", true}
{"one", true}, {"two", true}, {"three", false}, {"three", false}
};
json j_ummap(c_ummap); // only one entry for key "three" is used
@@ -92,7 +92,7 @@ int main()
json j_set(c_set); // only one entry for "one" is used
// create an array from std::unordered_set
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
std::unordered_set<std::string> c_uset {"one", "one"};
json j_uset(c_uset); // only one entry for "one" is used
// create an array from std::multiset
@@ -100,7 +100,7 @@ int main()
json j_mset(c_mset); // both entries for "one" are used
// create an array from std::unordered_multiset
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
std::unordered_multiset<std::string> c_umset {"one", "one"};
json j_umset(c_umset); // both entries for "one" are used
// serialize the JSON arrays
@@ -12,9 +12,9 @@
[12345678909876,23456789098765,34567890987654,45678909876543]
[1,2,3,4]
["four","one","three","two"]
["four","three","two","one"]
["one"]
["four","one","one","two"]
["four","two","one","one"]
["one","one"]
"The quick brown fox jumps over the lazy dog."
"The quick brown fox jumps over the lazy dog."
@@ -0,0 +1,23 @@
#include <iostream>
#include <nlohmann/json.hpp>
// define a byte container based on std::vector
using byte_container_with_subtype = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>;
int main()
{
std::vector<std::uint8_t> bytes = {{0xca, 0xfe, 0xba, 0xbe}};
// create containers without and with a subtype
auto c1 = byte_container_with_subtype(bytes);
auto c2 = byte_container_with_subtype(bytes);
auto c3 = byte_container_with_subtype(bytes, 42);
auto c4 = byte_container_with_subtype(bytes, 42);
auto c5 = byte_container_with_subtype(bytes, 23);
std::cout << std::boolalpha
<< "c1 == c2: " << (c1 == c2) << '\n'
<< "c1 == c3: " << (c1 == c3) << '\n'
<< "c3 == c4: " << (c3 == c4) << '\n'
<< "c3 == c5: " << (c3 == c5) << std::endl;
}
@@ -0,0 +1,4 @@
c1 == c2: true
c1 == c3: false
c3 == c4: true
c3 == c5: false
@@ -0,0 +1,23 @@
#include <iostream>
#include <nlohmann/json.hpp>
// define a byte container based on std::vector
using byte_container_with_subtype = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>;
int main()
{
std::vector<std::uint8_t> bytes = {{0xca, 0xfe, 0xba, 0xbe}};
// create containers without and with a subtype
auto c1 = byte_container_with_subtype(bytes);
auto c2 = byte_container_with_subtype(bytes);
auto c3 = byte_container_with_subtype(bytes, 42);
auto c4 = byte_container_with_subtype(bytes, 42);
auto c5 = byte_container_with_subtype(bytes, 23);
std::cout << std::boolalpha
<< "c1 != c2: " << (c1 != c2) << '\n'
<< "c1 != c3: " << (c1 != c3) << '\n'
<< "c3 != c4: " << (c3 != c4) << '\n'
<< "c3 != c5: " << (c3 != c5) << std::endl;
}
@@ -0,0 +1,4 @@
c1 != c2: false
c1 != c3: true
c3 != c4: false
c3 != c5: true
@@ -1,5 +1,6 @@
#pragma once
#include <cstddef>
#include <ostream>
#include <string>
@@ -8,10 +9,10 @@
// and nothing more of std::string's interface.
//
// Covers the "Always required" members, the extras needed for the binary
// formats, and the extras needed for JSON Pointer / flatten / unflatten /
// diff. Extending it further (e.g. for std::hash<basic_json> or to_bson) is
// a matter of adding the extra members listed in the "Required for other
// functionality" table.
// formats, JSON Pointer / flatten / unflatten, and the int_to_string overload
// needed for diff and items. Extending it further (e.g. for
// std::hash<basic_json> or to_bson) is a matter of adding the extra members
// listed in the "Required for other functionality" table.
//
// See https://json.nlohmann.me/features/types/template_parameters/#stringtype
class custom_string_type
@@ -93,6 +94,11 @@ class custom_string_type
data_.append(other.data_);
return *this;
}
custom_string_type& operator+=(char c)
{
data_.push_back(c);
return *this;
}
size_type find_first_of(char c, size_type pos = 0) const
{
@@ -116,6 +122,12 @@ class custom_string_type
return data_.end();
}
// found by ADL; converts array indices to keys in diff and items
friend void int_to_string(custom_string_type& target, std::size_t value)
{
target.data_ = std::to_string(value);
}
friend bool operator==(const custom_string_type& lhs, const custom_string_type& rhs)
{
return lhs.data_ == rhs.data_;
@@ -0,0 +1,23 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value with an empty object and an empty array
json j =
{
{"empty_object", json::object()},
{"empty_array", json::array()},
{"name", "Niels"}
};
// call flatten()
json flattened = j.flatten();
std::cout << std::setw(4) << flattened << "\n\n";
// the empty containers cannot be restored by unflatten()
std::cout << std::setw(4) << flattened.unflatten() << '\n';
}
@@ -0,0 +1,11 @@
{
"/empty_array": null,
"/empty_object": null,
"/name": "Niels"
}
{
"empty_array": null,
"empty_object": null,
"name": "Niels"
}
@@ -0,0 +1,17 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json;
int main()
{
// create a JSON value
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
// convert to a different basic_json specialization
ordered_json oj = j.get<ordered_json>();
std::cout << j << '\n';
std::cout << oj << '\n';
}
@@ -0,0 +1,2 @@
{"one":1,"three":3,"two":2}
{"one":1,"three":3,"two":2}
@@ -1,5 +1,5 @@
#include <iostream>
#include <unordered_map>
#include <map>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
@@ -29,7 +29,7 @@ int main()
auto v5 = json_types["number"]["floating-point"].get<int>();
auto v6 = json_types["string"].get<std::string>();
auto v7 = json_types["array"].get<std::vector<short>>();
auto v8 = json_types.get<std::unordered_map<std::string, json>>();
auto v8 = json_types.get<std::map<std::string, json>>();
// print the conversion results
std::cout << v1 << '\n';
@@ -4,8 +4,8 @@
Hello, world!
1 2 3 4 5
number: {"floating-point":17.23,"integer":42}
null: null
string: "Hello, world!"
boolean: true
array: [1,2,3,4,5]
boolean: true
null: null
number: {"floating-point":17.23,"integer":42}
string: "Hello, world!"
+2 -2
View File
@@ -1,5 +1,5 @@
#include <iostream>
#include <unordered_map>
#include <map>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
@@ -28,7 +28,7 @@ int main()
int v5;
std::string v6;
std::vector<short> v7;
std::unordered_map<std::string, json> v8;
std::map<std::string, json> v8;
// use explicit conversions
json_types["boolean"].get_to(v1);
+4 -4
View File
@@ -4,8 +4,8 @@
Hello, world!
1 2 3 4 5
number: {"floating-point":17.23,"integer":42}
null: null
string: "Hello, world!"
boolean: true
array: [1,2,3,4,5]
boolean: true
null: null
number: {"floating-point":17.23,"integer":42}
string: "Hello, world!"
@@ -0,0 +1,22 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// parsing invalid JSON without exceptions yields a discarded value
json j_invalid = json::parse("[1,2,3", nullptr, false);
// a callback that discards the top-level value does not leave it
// "discarded" -- it is replaced by null instead
json j_discarded_by_callback = json::parse("[1,2,3]", [](int /*depth*/, json::parse_event_t event, json& /*parsed*/)
{
return event != json::parse_event_t::array_start;
});
std::cout << std::boolalpha;
std::cout << "j_invalid.is_discarded() = " << j_invalid.is_discarded() << '\n';
std::cout << "j_discarded_by_callback = " << j_discarded_by_callback << '\n';
std::cout << "j_discarded_by_callback.is_discarded() = " << j_discarded_by_callback.is_discarded() << '\n';
}
@@ -0,0 +1,3 @@
j_invalid.is_discarded() = true
j_discarded_by_callback = null
j_discarded_by_callback.is_discarded() = false
@@ -0,0 +1,32 @@
#include <compare>
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
const char* to_string(const std::strong_ordering& so)
{
if (std::is_lt(so))
{
return "less";
}
else if (std::is_gt(so))
{
return "greater";
}
return "equal";
}
int main()
{
// different JSON pointers
json::json_pointer ptr1("/a/b");
json::json_pointer ptr2("/a/c");
json::json_pointer ptr3("/a/b/c");
json::json_pointer ptr4("/a/b");
// 3-way compare JSON pointers
std::cout << "\"" << ptr1 << "\" <=> \"" << ptr2 << "\": " << to_string(ptr1 <=> ptr2) << '\n' // *NOPAD*
<< "\"" << ptr1 << "\" <=> \"" << ptr3 << "\": " << to_string(ptr1 <=> ptr3) << '\n' // *NOPAD*
<< "\"" << ptr1 << "\" <=> \"" << ptr4 << "\": " << to_string(ptr1 <=> ptr4) << std::endl; // *NOPAD*
}
@@ -0,0 +1,3 @@
"/a/b" <=> "/a/c": less
"/a/b" <=> "/a/b/c": less
"/a/b" <=> "/a/b": equal
@@ -1,5 +1,5 @@
#include <iostream>
#include <unordered_map>
#include <map>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
@@ -29,7 +29,7 @@ int main()
int v5 = json_types["number"]["floating-point"];
std::string v6 = json_types["string"];
std::vector<short> v7 = json_types["array"];
std::unordered_map<std::string, json> v8 = json_types;
std::map<std::string, json> v8 = json_types;
// print the conversion results
std::cout << v1 << '\n';
@@ -4,9 +4,9 @@
Hello, world!
1 2 3 4 5
number: {"floating-point":17.23,"integer":42}
null: null
string: "Hello, world!"
boolean: true
array: [1,2,3,4,5]
boolean: true
null: null
number: {"floating-point":17.23,"integer":42}
string: "Hello, world!"
[json.exception.type_error.302] type must be boolean, but is string
@@ -0,0 +1,44 @@
#include <iostream>
#include <string>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// translate a parse_event_t to a human-readable name
std::string event_name(json::parse_event_t event)
{
switch (event)
{
case json::parse_event_t::object_start:
return "object_start";
case json::parse_event_t::object_end:
return "object_end";
case json::parse_event_t::array_start:
return "array_start";
case json::parse_event_t::array_end:
return "array_end";
case json::parse_event_t::key:
return "key";
case json::parse_event_t::value:
return "value";
default:
return "unknown";
}
}
int main()
{
// a small JSON text
auto text = R"({"pi": 3.141, "numbers": [1, 2]})";
// parse the text and report every event together with its depth;
// returning true keeps every value unchanged
json j = json::parse(text, [](int depth, json::parse_event_t event, json& /*parsed*/)
{
std::cout << depth << " " << event_name(event) << '\n';
return true;
});
// the callback did not change anything, so the parsed value is unaffected
std::cout << j << '\n';
}
@@ -0,0 +1,10 @@
0 object_start
1 key
1 value
1 key
1 array_start
2 value
2 value
1 array_end
0 object_end
{"numbers":[1,2],"pi":3.141}
@@ -0,0 +1,36 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using namespace nlohmann::literals;
int main()
{
// the original document
json doc = R"(
{
"a": { "b": 1 }
}
)"_json;
// a patch that tries to move "/a" into one of its own children
json patch = R"(
[
{ "op": "move", "from": "/a", "path": "/a/b" }
]
)"_json;
// exception out_of_range.414
try
{
json patched_doc = doc.patch(patch);
}
catch (const json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// the original document is unchanged
std::cout << std::setw(4) << doc << std::endl;
}
@@ -0,0 +1,6 @@
[json.exception.out_of_range.414] cannot move value: 'from' path '/a' is a proper prefix of 'path' '/a/b'
{
"a": {
"b": 1
}
}
@@ -0,0 +1,38 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using namespace nlohmann::literals;
int main()
{
// the original document
json doc = R"(
{
"a": 1,
"b": 2
}
)"_json;
// a patch whose second operation fails
json patch = R"(
[
{ "op": "replace", "path": "/a", "value": 99 },
{ "op": "remove", "path": "/nonexistent" }
]
)"_json;
// exception out_of_range.403
try
{
doc.patch_inplace(patch);
}
catch (const json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// the first operation has already been applied to doc
std::cout << std::setw(4) << doc << std::endl;
}
@@ -0,0 +1,5 @@
[json.exception.out_of_range.403] key 'nonexistent' not found
{
"a": 99,
"b": 2
}
@@ -0,0 +1,40 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// a DOM parser that reports parse errors instead of throwing
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>
{
public:
explicit sax_no_exception(json& j)
: nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>(j, false)
{}
bool parse_error(std::size_t position,
const std::string& last_token,
const json::exception& ex)
{
std::cout << "parse error at input byte " << position << "\n"
<< ex.what() << "\n"
<< "last read: \"" << last_token << "\""
<< std::endl;
return false;
}
};
int main()
{
std::string myinput = "[1,2,3,]";
json result;
sax_no_exception sax(result);
bool parse_result = json::sax_parse(myinput, &sax);
if (!parse_result)
{
std::cout << "parsing unsuccessful!" << std::endl;
}
std::cout << "parsed value: " << result << std::endl;
}
@@ -0,0 +1,5 @@
parse error at input byte 8
[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
last read: "3,]"
parsing unsuccessful!
parsed value: [1,2,3]
@@ -0,0 +1,20 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a non-empty JSON array
json j = {1, 2, 3};
// exception other_error.502
try
{
json::to_bjdata(j, false, true);
}
catch (const json::other_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1 @@
[json.exception.other_error.502] use_type requires use_size = true
@@ -0,0 +1,22 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON string that is not valid UTF-8
std::string invalid_utf8;
invalid_utf8.push_back(static_cast<char>(0xFF));
json j = invalid_utf8;
// exception type_error.316
try
{
json::to_bon8(j);
}
catch (const json::type_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1 @@
[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF
@@ -0,0 +1,23 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON object whose key contains a null byte (U+0000)
std::string key = "ab";
key.push_back('\0');
key.push_back('c');
json j = {{key, 1}};
// exception out_of_range.409
try
{
json::to_bson(j);
}
catch (const json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1 @@
[json.exception.out_of_range.409] BSON key cannot contain code point U+0000 (at byte 2)
@@ -0,0 +1,20 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value with a binary subtype that exceeds 255
json j = json::binary({1, 2, 3}, 300);
// exception out_of_range.415
try
{
json::to_msgpack(j);
}
catch (const json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1 @@
[json.exception.out_of_range.415] subtype 300 is too large for the MessagePack ext type (max 255)
@@ -0,0 +1,20 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a non-empty JSON array
json j = {1, 2, 3};
// exception other_error.502
try
{
json::to_ubjson(j, false, true);
}
catch (const json::other_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1 @@
[json.exception.other_error.502] use_type requires use_size = true
@@ -0,0 +1,33 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON object with a string value
json j = {{"name", "the good"}};
// exception type_error.302
try
{
int v = j.value("name", 0);
std::cout << v << '\n';
}
catch (const json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception type_error.306
try
{
json str = "I am a string";
auto v = str.value("name", 0);
std::cout << v << '\n';
}
catch (const json::type_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1,2 @@
[json.exception.type_error.302] type must be number, but is string
[json.exception.type_error.306] cannot use value() with string