mirror of
https://github.com/nlohmann/json.git
synced 2026-10-03 05:00:30 +00:00
Document json_document and json_view
- API pages for basic_json_document and basic_json_view, one per member, and for the four aliases, each with an example - features/json_view.md: the problem the view solves, ownership and lifetime, what matches basic_json::parse() and what differs, and when to choose json, ordered_json, SAX, or the view - the examples show why one would use the view, not only how: borrowed vs. owned input, reading a few fields and materializing one subtree, reusing a document across many messages - registered in the mkdocs navigation, llms.txt, the docset, the exceptions page (out_of_range.416), architecture.md, the integration page, and the README; the yyjson credit is added to the README and license.md Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// accept() behaves exactly like basic_json::accept(): the same inputs are
|
||||
// accepted or rejected, with the same ignore_comments/ignore_trailing_commas
|
||||
// options
|
||||
std::cout << json_document::accept(R"({"a": 1})") << '\n';
|
||||
std::cout << json_document::accept(R"({"a": 1,})") << '\n'; // trailing comma: rejected by default
|
||||
std::cout << json_document::accept(R"({"a": 1,})", false, true) << '\n'; // ignore_trailing_commas
|
||||
|
||||
std::cout << (json_document::accept(R"({"a": 1})") == nlohmann::json::accept(R"({"a": 1})")) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
true
|
||||
false
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// the default constructor creates an empty (discarded) document
|
||||
json_document empty;
|
||||
std::cout << empty.is_discarded() << '\n';
|
||||
|
||||
// json_document is move-only: parse() itself returns by value (moved out),
|
||||
// and a document can be moved again, e.g. into a container
|
||||
json_document doc = json_document::parse(R"({"a": 1})");
|
||||
json_document moved = std::move(doc);
|
||||
std::cout << moved.root().is_object() << '\n';
|
||||
|
||||
// copying is disabled at compile time:
|
||||
// json_document another = moved; // does not compile
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// with allow_exceptions == false, a parse error produces a discarded
|
||||
// document instead of throwing -- exactly like basic_json::parse()
|
||||
json_document doc = json_document::parse(R"({"a": )", /* allow_exceptions */ false);
|
||||
std::cout << doc.is_discarded() << '\n';
|
||||
std::cout << doc.root().is_discarded() << '\n';
|
||||
|
||||
// a successful parse is never discarded
|
||||
json_document ok = json_document::parse(R"({"a": 1})", false);
|
||||
std::cout << ok.is_discarded() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
true
|
||||
true
|
||||
false
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// long enough that copying it needs a real (heap) allocation, so the
|
||||
// comparison below does not depend on the standard library's small
|
||||
// string optimization threshold
|
||||
const std::string text = std::string(200, ' ') + "[1, 2, 3, 4, 5]";
|
||||
|
||||
// memory_usage() is not portable across platforms/allocators/compilers, so
|
||||
// compare it relatively instead of printing the raw byte count
|
||||
json_document borrowed = json_document::parse(text);
|
||||
json_document owned = json_document::parse_copy(text);
|
||||
|
||||
// the owned document additionally stores its own copy of the source text
|
||||
std::cout << (owned.memory_usage() > borrowed.memory_usage()) << '\n';
|
||||
|
||||
// a document with more values needs a larger index
|
||||
json_document small = json_document::parse(std::string("[1]"));
|
||||
json_document large = json_document::parse(std::string("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"));
|
||||
std::cout << (large.memory_usage() > small.memory_usage()) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
// node_count() is the size of the flat index: one 16-byte node per value,
|
||||
// plus one per object key (values and keys are all the index stores)
|
||||
json_document scalar = json_document::parse("42");
|
||||
std::cout << scalar.node_count() << '\n';
|
||||
|
||||
json_document doc = json_document::parse(R"({"a": 1, "b": [1, 2]})");
|
||||
std::cout << doc.node_count() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
1
|
||||
7
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
std::string text = R"({"a": 1})";
|
||||
|
||||
// borrowed: the document only points into `text`; `text` must outlive it
|
||||
json_document borrowed = json_document::parse(text);
|
||||
std::cout << borrowed.owns_source() << '\n';
|
||||
|
||||
// owned: parse_copy() always takes its own copy
|
||||
json_document copied = json_document::parse_copy(text);
|
||||
std::cout << copied.owns_source() << '\n';
|
||||
|
||||
// owned: an rvalue std::string is moved in, not copied, but still owned
|
||||
json_document moved_in = json_document::parse(std::string(text));
|
||||
std::cout << moved_in.owns_source() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
false
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// an lvalue std::string is BORROWED: the document only stores a pointer
|
||||
// into `text`, so `text` must outlive `borrowed`
|
||||
std::string text = R"({"count": 3})";
|
||||
json_document borrowed = json_document::parse(text);
|
||||
std::cout << borrowed.owns_source() << '\n'; // false
|
||||
|
||||
// an rvalue std::string is MOVED into the document -- no copy of the text
|
||||
json_document owned = json_document::parse(std::string(R"({"count": 3})"));
|
||||
std::cout << owned.owns_source() << '\n'; // true
|
||||
|
||||
// errors are identical to basic_json::parse: same exception id, message,
|
||||
// and position, because the library parser runs on the same bytes on a
|
||||
// failing input
|
||||
try
|
||||
{
|
||||
static_cast<void>(json_document::parse(R"({"count": )"));
|
||||
}
|
||||
catch (const nlohmann::json::parse_error& e)
|
||||
{
|
||||
std::cout << e.id << '\n';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
false
|
||||
true
|
||||
101
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
json_document parse_from_temporary_buffer()
|
||||
{
|
||||
char buffer[] = R"({"a": 1})";
|
||||
// parse() would borrow `buffer`, which is about to go out of scope;
|
||||
// parse_copy() takes its own copy instead, so the returned document does
|
||||
// not depend on `buffer` afterward
|
||||
return json_document::parse_copy(buffer);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
json_document doc = parse_from_temporary_buffer();
|
||||
std::cout << doc.owns_source() << '\n';
|
||||
std::cout << doc.root().is_object() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// a JSON value embedded in a larger, non-null-terminated buffer (e.g. a
|
||||
// slice received over the network)
|
||||
std::vector<char> buffer = {'[', '1', ',', '2', ']', 'j', 'u', 'n', 'k'};
|
||||
|
||||
// a pointer pair is BORROWED, exactly like a byte container lvalue: the
|
||||
// document points into the buffer. (From C++20 on, std::vector<char>
|
||||
// iterators are borrowed as well; before, they are copied.)
|
||||
const char* first = buffer.data();
|
||||
json_document doc = json_document::parse(first, first + 5);
|
||||
std::cout << doc.root().is_array() << ' ' << doc.root().size() << '\n';
|
||||
std::cout << doc.owns_source() << '\n'; // false: borrowed
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
true 2
|
||||
false
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
std::vector<std::string> messages =
|
||||
{
|
||||
R"({"id": 1})", R"({"id": 2, "tag": "x"})", R"({"id": 3})"
|
||||
};
|
||||
|
||||
// parse into the same document over and over: its node index and decode
|
||||
// buffer are reused instead of being freed and reallocated for each message
|
||||
json_document doc;
|
||||
std::size_t total = 0;
|
||||
for (const auto& msg : messages)
|
||||
{
|
||||
doc.read(msg);
|
||||
total += doc.root().size();
|
||||
}
|
||||
std::cout << total << '\n';
|
||||
|
||||
// read() can also change what kind of input is owned/borrowed between calls
|
||||
doc.read(std::string(R"({"owned": true})"));
|
||||
std::cout << doc.owns_source() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
4
|
||||
true
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
json_document doc = json_document::parse(R"({"greeting": "hi"})");
|
||||
std::cout << doc.root().is_object() << '\n';
|
||||
|
||||
// root() is a cheap handle, not a copy: repeated calls observe the same value
|
||||
std::cout << (doc.root().type() == doc.root().type()) << '\n';
|
||||
|
||||
// the root of a failed parse (allow_exceptions == false) is discarded
|
||||
json_document failed = json_document::parse("{", false);
|
||||
std::cout << failed.root().is_discarded() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
true
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// build a large array (many nodes), then read a small one into the same
|
||||
// document: the index grown for the large input is still allocated
|
||||
std::ostringstream big;
|
||||
big << '[';
|
||||
for (int i = 0; i < 500; ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
big << ',';
|
||||
}
|
||||
big << i;
|
||||
}
|
||||
big << ']';
|
||||
|
||||
json_document doc;
|
||||
doc.read(big.str());
|
||||
const std::size_t big_nodes = doc.node_count();
|
||||
|
||||
doc.read(std::string("[1]"));
|
||||
std::cout << (doc.node_count() < big_nodes) << '\n'; // far fewer live nodes now
|
||||
const std::size_t before = doc.memory_usage();
|
||||
|
||||
// shrink_to_fit() moves the index into a block sized for what is actually
|
||||
// used. This INVALIDATES every view taken from this document before the
|
||||
// call (they point into the old, now-freed block) -- take fresh ones from
|
||||
// root() afterward.
|
||||
doc.shrink_to_fit();
|
||||
const std::size_t after = doc.memory_usage();
|
||||
std::cout << (after <= before) << '\n';
|
||||
|
||||
// a freshly taken view is valid and correct
|
||||
std::cout << doc.root().is_array() << ' ' << doc.root().size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
true
|
||||
true
|
||||
true 1
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
std::string text = R"({"a": 1})";
|
||||
json_document doc = json_document::parse(text);
|
||||
|
||||
// source() is the parsed text, whether borrowed or owned
|
||||
std::cout << (doc.source().size() == text.size()) << '\n';
|
||||
std::cout << std::string(doc.source().data(), doc.source().size()) << '\n';
|
||||
|
||||
// for a borrowed document, source() points right into the caller's buffer
|
||||
std::cout << (doc.source().data() == text.data()) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
true
|
||||
{"a": 1}
|
||||
true
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// the default constructor is the only public one: it creates an invalid
|
||||
// (discarded) view, useful as a "no value yet" placeholder
|
||||
nlohmann::json_view v;
|
||||
std::cout << static_cast<bool>(v) << ' ' << v.is_discarded() << '\n';
|
||||
|
||||
// views are trivially copyable handles (two pointers); the document owns
|
||||
// the actual data
|
||||
nlohmann::json_view copy = v;
|
||||
std::cout << static_cast<bool>(copy) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
false true
|
||||
false
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
// three incoming messages; skip the ones that are not useful without ever
|
||||
// building a nlohmann::json value for them
|
||||
json_document heartbeat = json_document::parse("null");
|
||||
json_document empty_batch = json_document::parse("[]");
|
||||
json_document batch = json_document::parse(R"([{"id": 1}, {"id": 2}, {"id": 3}])");
|
||||
std::array<const json_document*, 3> messages = {{&heartbeat, &empty_batch, &batch}};
|
||||
|
||||
for (const json_document* d : messages)
|
||||
{
|
||||
// is_array()/empty() only look at the flat index: a discarded
|
||||
// heartbeat or an empty batch is never turned into a nlohmann::json
|
||||
// value, so no per-element allocation happens for them
|
||||
if (!d->root().is_array() || d->root().empty())
|
||||
{
|
||||
std::cout << "skipped\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// materialize() replays the subtree through the same SAX builder
|
||||
// basic_json::parse() uses, so the result is exactly what
|
||||
// basic_json::parse() would have produced for the same text
|
||||
nlohmann::json value = d->root().materialize();
|
||||
std::cout << value.dump() << '\n';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
skipped
|
||||
skipped
|
||||
[{"id":1},{"id":2},{"id":3}]
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// decide whether a batch is worth processing before building any
|
||||
// nlohmann::json value for it
|
||||
json_document batch = json_document::parse(R"([1, 2, 3, 4, 5])");
|
||||
json_document empty_batch = json_document::parse("[]");
|
||||
|
||||
std::cout << batch.root().empty() << ' ' << batch.root().size() << '\n';
|
||||
std::cout << empty_batch.root().empty() << ' ' << empty_batch.root().size() << '\n';
|
||||
|
||||
// as for basic_json: null has size 0, every other scalar has size 1
|
||||
json_document n = json_document::parse("null");
|
||||
json_document s = json_document::parse(R"("hi")");
|
||||
std::cout << n.root().size() << ' ' << s.root().size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
false 5
|
||||
true 0
|
||||
0 1
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// source_offset() points into source(): useful to report *where* in the
|
||||
// original text a value came from (error messages, syntax highlighting,
|
||||
// forwarding a sub-range verbatim, ...) without materializing it
|
||||
json_document doc = json_document::parse(R"( 123)");
|
||||
auto v = doc.root();
|
||||
std::cout << v.source_offset() << ' '
|
||||
<< std::string(doc.source().data() + v.source_offset(), 3) << '\n';
|
||||
|
||||
// a string without escapes also stays in the source text
|
||||
json_document plain = json_document::parse(R"("ab")");
|
||||
std::cout << plain.source()[plain.root().source_offset()] << '\n';
|
||||
|
||||
// a string with escapes is decoded once into the document's own buffer, so
|
||||
// there is no single byte range in source() to point at: source_offset()
|
||||
// returns the "not applicable" sentinel
|
||||
json_document escaped = json_document::parse(R"("a\nb")");
|
||||
std::cout << (escaped.root().source_offset() == static_cast<std::size_t>(-1)) << '\n';
|
||||
|
||||
// a discarded view -- default-constructed, or the root of a failed parse
|
||||
// with allow_exceptions == false -- has no offset either
|
||||
json_document failed = json_document::parse("not json", false);
|
||||
std::cout << (failed.root().source_offset() == static_cast<std::size_t>(-1)) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
2 123
|
||||
a
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// several incoming messages, one json_document per message. type() and
|
||||
// is_*() only look at the flat index built by parse(); no nlohmann::json
|
||||
// tree exists yet, and none is built unless materialize() is called
|
||||
json_document d_null = json_document::parse("null");
|
||||
json_document d_bool = json_document::parse("true");
|
||||
json_document d_int = json_document::parse("-42");
|
||||
json_document d_unsigned = json_document::parse("42");
|
||||
json_document d_float = json_document::parse("4.2");
|
||||
json_document d_string = json_document::parse(R"("hi")");
|
||||
json_document d_array = json_document::parse("[1, 2, 3]");
|
||||
json_document d_object = json_document::parse(R"({"a": 1})");
|
||||
|
||||
std::cout << d_null.root().is_null() << '\n';
|
||||
std::cout << d_bool.root().is_boolean() << '\n';
|
||||
std::cout << d_int.root().is_number() << ' ' << d_int.root().is_number_integer() << '\n';
|
||||
std::cout << d_unsigned.root().is_number_unsigned() << '\n';
|
||||
std::cout << d_float.root().is_number_float() << '\n';
|
||||
std::cout << d_string.root().is_string() << '\n';
|
||||
std::cout << d_array.root().is_array() << ' ' << d_array.root().is_structured() << '\n';
|
||||
std::cout << d_object.root().is_object() << ' ' << d_object.root().is_primitive() << '\n';
|
||||
|
||||
// JSON text can never produce a binary value: is_binary() is always false
|
||||
std::cout << d_array.root().is_binary() << '\n';
|
||||
|
||||
// a default-constructed view, and the root of a document that failed to
|
||||
// parse without exceptions, are both discarded
|
||||
nlohmann::json_view invalid;
|
||||
json_document failed = json_document::parse("not json", /* allow_exceptions */ false);
|
||||
std::cout << static_cast<bool>(invalid) << ' ' << invalid.is_discarded() << '\n';
|
||||
std::cout << static_cast<bool>(failed.root()) << ' ' << failed.root().is_discarded() << '\n';
|
||||
|
||||
// type() returns the same value_t enumeration as basic_json::type()
|
||||
std::cout << (d_object.root().type() == nlohmann::json::value_t::object) << '\n';
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
true
|
||||
true
|
||||
true true
|
||||
true
|
||||
true
|
||||
true
|
||||
true true
|
||||
true false
|
||||
false
|
||||
false true
|
||||
false true
|
||||
true
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// json_document is basic_json_document<nlohmann::json>: same value types
|
||||
// and containers as the ordinary json specialization
|
||||
json_document doc = json_document::parse(R"({"pi": 3.14, "numbers": [1, 2, 3]})");
|
||||
|
||||
std::cout << doc.root().is_object() << '\n';
|
||||
std::cout << doc.root().materialize().dump() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
true
|
||||
{"numbers":[1,2,3],"pi":3.14}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// json_view is basic_json_view<nlohmann::json>: a read-only handle
|
||||
// returned by json_document::root()
|
||||
nlohmann::json_document doc = nlohmann::json_document::parse("[1, 2, 3]");
|
||||
nlohmann::json_view v = doc.root();
|
||||
|
||||
std::cout << v.is_array() << ' ' << v.size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true 3
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using json_document = nlohmann::json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// BORROWED: doc only points into `text`; `text` must outlive `doc`
|
||||
std::string text = R"({"a": 1})";
|
||||
json_document doc = json_document::parse(text);
|
||||
std::cout << doc.owns_source() << '\n'; // false
|
||||
|
||||
// a view is valid as long as the document is alive, has not been
|
||||
// re-parsed (read()) or shrunk (shrink_to_fit()), and -- if borrowed --
|
||||
// the source text is alive
|
||||
nlohmann::json_view v = doc.root();
|
||||
std::cout << v.is_object() << '\n';
|
||||
|
||||
// re-parsing the SAME document invalidates views taken before the call;
|
||||
// `v` above must not be used after this line
|
||||
doc.read(R"([1, 2, 3])");
|
||||
v = doc.root(); // take a fresh view instead
|
||||
std::cout << v.is_array() << '\n';
|
||||
|
||||
// moving the document does not invalidate views: the node index is
|
||||
// heap-allocated and does not move with the document object
|
||||
json_document moved = std::move(doc);
|
||||
std::cout << v.is_array() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
false
|
||||
true
|
||||
true
|
||||
true
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
using ordered_json_document = nlohmann::ordered_json_document;
|
||||
|
||||
int main()
|
||||
{
|
||||
// ordered_json_document is basic_json_document<nlohmann::ordered_json>:
|
||||
// materialize() preserves the insertion (source) order of object keys,
|
||||
// instead of sorting them like json_document does
|
||||
ordered_json_document doc = ordered_json_document::parse(R"({"z": 1, "a": 2, "m": 3})");
|
||||
std::cout << doc.root().materialize().dump() << '\n';
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"z":1,"a":2,"m":3}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_json_document doc = nlohmann::ordered_json_document::parse(R"({"z": 1, "a": 2})");
|
||||
nlohmann::ordered_json_view v = doc.root();
|
||||
|
||||
std::cout << std::boolalpha << v.is_object() << ' ' << v.size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true 2
|
||||
Reference in New Issue
Block a user