mirror of
https://github.com/nlohmann/json.git
synced 2026-10-28 08:45:43 +00:00
docs: new design for the documentation site (#5934)
* docs: new design for the documentation site Apply the brand to the Material for MkDocs site: Inter and JetBrains Mono served by the site (upright and real italic), brand colours, blue header band with the syntax pattern, wordmark in the header, new home page (hero, cards, animated feature tour), 404 page, polish for tabs, search, footer, focus rings, tables and code blocks, and theme features (code copy, previous/next footer, TOC follow, search suggestions). Draw the number railroad diagram, the parser callback events and the iterator illustrations as inline SVGs that follow the light and dark scheme. The generator scripts are in docs/mkdocs/scripts/figures; the feature slideshow (json-light.svg, json-dark.svg, replacing json.gif on the home page) is built by docs/mkdocs/scripts/slideshow. Decision nodes in five flowcharts become hexagons, which need far less room. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * docs: add figures, table captions and a macro chooser - Figures with numbered captions: SAX stepper, json_view layout and edit stepper, exception map, JSON pointer and patch walkers, QA pipeline, scaling and binary size charts, roadmap lanes, release timeline, integration decision tree and namespace builder - Table captions (nj-table-caption) on 9 pages - Compile times: modules and PCH charts, filesystem section, re-measured Figure 1, links between features/modules.md and compile_times.md - Interactive macro chooser for features/arbitrary_types.md - Link check: exclude URLs that answer the plugin with 400/401/419 or are dead (customers.md) Signed-off-by: Niels Lohmann <mail@nlohmann.me> * docs: macro chooser generates adl_serializer for non-default-constructible types Signed-off-by: Niels Lohmann <mail@nlohmann.me> * docs: cross-link concept pages and API pages in See also sections Add See also links in both directions between the concept pages (features, home, integration) and the API pages, write API links in code font, give every entry a comment after a dash, and show the callback event figure on the parser callbacks page. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * docs: address review comments on the new design - Home: add a "Latest release" button - Sponsors: update the list and group it by tier - Features: list all feature pages on the index page - Releases: add highlights per release, link the 4.0 roadmap, add the first commit to the timeline - Exceptions: prefix all example messages with the exception name - API: no code font for format names in the See also links of the to_/from_ pages - Merge Patch: show the document before, the patch, and the result - Replace "--" with typographic dashes, mark external links with an icon, center Mermaid diagrams Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
2bb2feeef4
commit
a47170346a
417 files changed
+11100
-3041
No files matched your search
@@ -0,0 +1,412 @@
|
||||
<!--
|
||||
Feature slides for the animated slideshow. build.py adds the title slide before them and the closing slide after them.
|
||||
|
||||
# Title one slide per heading; `{badge: TEXT}` at the end adds a red chip
|
||||
- bullet bullets; a long bullet may continue on indented lines
|
||||
```cpp ... ``` the code shown on the right (a line starting with `$ ` is a shell command)
|
||||
-->
|
||||
|
||||
# Trivial integration
|
||||
|
||||
- single header file
|
||||
- no build system needed
|
||||
- vanilla C++11
|
||||
- works with GCC 4.8+, Clang 3.4+ and MSVC 2015+
|
||||
|
||||
```cpp
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// for convenience
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON pretty-printer in 3 lines
|
||||
json j;
|
||||
std::cin >> j;
|
||||
std::cout << std::setw(4) << j << std::endl;
|
||||
}
|
||||
|
||||
$ g++ pretty.cpp -std=c++11 -o pretty
|
||||
```
|
||||
|
||||
# First-class datatype
|
||||
|
||||
- write JSON like any other C++ literal
|
||||
- initializer lists become arrays and objects
|
||||
|
||||
```cpp
|
||||
json j = {
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{"answer", {
|
||||
{"everything", 42}
|
||||
}},
|
||||
{"list", {1, 0, 2}},
|
||||
{"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99}
|
||||
}}
|
||||
};
|
||||
```
|
||||
|
||||
# Array construction
|
||||
|
||||
- arrays work the way you expect
|
||||
- adding to a null value makes it an array
|
||||
|
||||
```cpp
|
||||
// create null value
|
||||
json j;
|
||||
|
||||
// add via member function
|
||||
j.push_back("Hello");
|
||||
j.emplace_back("World");
|
||||
|
||||
// add via += operator
|
||||
j += false;
|
||||
|
||||
// add via index
|
||||
j[2] = 42.3;
|
||||
|
||||
// gaps are filled with null
|
||||
j[4] = "World";
|
||||
```
|
||||
|
||||
# Object construction
|
||||
|
||||
- objects work the way you expect
|
||||
- adding to a null value makes it an object
|
||||
|
||||
```cpp
|
||||
// create null value
|
||||
json j;
|
||||
|
||||
// add via member function
|
||||
j.emplace("key2", "value");
|
||||
j.push_back({"key", "value"});
|
||||
|
||||
// add via += operator
|
||||
j += {"another key", false};
|
||||
|
||||
// add via key
|
||||
j["pi"] = 3.1415926;
|
||||
j["answer"]["everything"] = 42;
|
||||
```
|
||||
|
||||
# Container operations
|
||||
|
||||
- use JSON like an STL container
|
||||
- satisfies the ReversibleContainer requirements
|
||||
|
||||
```cpp
|
||||
// container empty?
|
||||
j.empty();
|
||||
|
||||
// current number of elements
|
||||
j.size();
|
||||
|
||||
// maximal number of elements
|
||||
j.max_size();
|
||||
|
||||
// swap elements
|
||||
j.swap(j2);
|
||||
std::swap(j, j2);
|
||||
|
||||
// clear a container
|
||||
j.clear();
|
||||
```
|
||||
|
||||
# STL containers
|
||||
|
||||
- switch between STL and JSON containers
|
||||
- conversion works in both directions
|
||||
|
||||
```cpp
|
||||
// some STL containers
|
||||
std::vector<int> v;
|
||||
std::unordered_map<std::string, bool> m;
|
||||
|
||||
// automatic transformation
|
||||
json j_array(v);
|
||||
json j_object(m);
|
||||
|
||||
// works both ways
|
||||
auto l = j_array.get<std::list<int>>();
|
||||
auto u = j_object
|
||||
.get<std::map<std::string, bool>>();
|
||||
```
|
||||
|
||||
# Type conversion
|
||||
|
||||
- convert your own types to and from JSON
|
||||
- one macro writes to_json and from_json
|
||||
- or write both functions for full control
|
||||
|
||||
```cpp
|
||||
// some user-defined type
|
||||
struct person {
|
||||
std::string name;
|
||||
int age;
|
||||
};
|
||||
|
||||
// defines to_json and from_json
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person,
|
||||
name, age)
|
||||
|
||||
// conversion in action
|
||||
person p {"Ned Flanders", 60};
|
||||
json j = p;
|
||||
// {"age": 60, "name": "Ned Flanders"}
|
||||
|
||||
auto p2 = j.get<person>();
|
||||
```
|
||||
|
||||
# Type deduction
|
||||
|
||||
- types are deduced automatically
|
||||
- member functions tell you the type
|
||||
|
||||
```cpp
|
||||
// type deduction
|
||||
json j1 = nullptr;
|
||||
json j2 = false;
|
||||
json j3 = 12.23;
|
||||
json j4 = {1, 2, 3};
|
||||
json j5 = {{"key", "value"}};
|
||||
json j6 = "Hello";
|
||||
|
||||
// quick checks
|
||||
j1.is_null();
|
||||
j2.is_boolean();
|
||||
j3.is_number();
|
||||
j4.is_array();
|
||||
j5.is_object();
|
||||
j6.is_string();
|
||||
```
|
||||
|
||||
# Serialization
|
||||
|
||||
- to a string or a stream
|
||||
- pretty-printing included
|
||||
|
||||
```cpp
|
||||
// default serialization
|
||||
auto s1 = j.dump();
|
||||
|
||||
// pretty-printed
|
||||
int indent = 4;
|
||||
std::string s2 = j.dump(indent);
|
||||
|
||||
// to stream
|
||||
std::cout << j << std::endl;
|
||||
|
||||
// pretty-printed
|
||||
std::cout << std::setw(indent) << j << std::endl;
|
||||
```
|
||||
|
||||
# Deserialization
|
||||
|
||||
- parse strings, streams and files
|
||||
- the _json literal puts plain JSON in your code
|
||||
- comments and trailing commas on request
|
||||
|
||||
```cpp
|
||||
// from string
|
||||
json j1 = json::parse("[1,null,false]");
|
||||
|
||||
// from file
|
||||
std::ifstream f("example.json");
|
||||
json j2 = json::parse(f);
|
||||
|
||||
// from string literal
|
||||
json j3 = "[3.14159]"_json;
|
||||
|
||||
// from raw string literal
|
||||
json j4 = R"(
|
||||
{"one": 1, "two": 2, "three": [1, 2, 3]}
|
||||
)"_json;
|
||||
```
|
||||
|
||||
# SAX parsing
|
||||
|
||||
- the parser can emit SAX events
|
||||
- process input without building a JSON value
|
||||
|
||||
```cpp
|
||||
// define a SAX event processor
|
||||
struct sax_processor : json::json_sax_t
|
||||
{
|
||||
bool boolean(bool val) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// implement other functions...
|
||||
};
|
||||
|
||||
// create object
|
||||
sax_processor my_processor;
|
||||
|
||||
// use it to process input
|
||||
json::sax_parse(input, &my_processor);
|
||||
```
|
||||
|
||||
# Zero-copy views {badge: NEW IN 3.13}
|
||||
|
||||
- parse without building a tree: 16 bytes per value
|
||||
- strings and numbers stay in the source text
|
||||
- materialize a json value only where you need one
|
||||
|
||||
```cpp
|
||||
#include <nlohmann/json_view.hpp>
|
||||
|
||||
// parse into a flat index, not a tree
|
||||
std::ifstream f("big.json");
|
||||
auto doc = nlohmann::json_document::parse(f);
|
||||
|
||||
// read-only views with familiar access
|
||||
auto view = doc.root();
|
||||
double pi = view["pi"].get<double>();
|
||||
for (auto v : view["list"])
|
||||
std::cout << v.get<int>() << '\n';
|
||||
|
||||
// build a json value only where needed
|
||||
json part = view["list"].materialize();
|
||||
```
|
||||
|
||||
# JSON Pointer
|
||||
|
||||
- address any element with a JSON Pointer
|
||||
- flatten a value to pointer/value pairs, and back
|
||||
|
||||
```cpp
|
||||
json j = {"good", "bad", "ugly"};
|
||||
|
||||
// JSON pointer to the 3rd list element
|
||||
auto ptr = json::json_pointer("/2");
|
||||
|
||||
// use JSON pointer to access element
|
||||
j[ptr] = {{"it", "cattivo"}};
|
||||
|
||||
// user-defined string literal
|
||||
j["/2/en"_json_pointer] = "ugly";
|
||||
// ["good","bad",{"en":"ugly","it":"cattivo"}]
|
||||
|
||||
json flat = j.flatten();
|
||||
// {"/0":"good","/1":"bad","/2/en":"ugly",
|
||||
// "/2/it":"cattivo"}
|
||||
|
||||
json j2 = flat.unflatten(); // j == j2
|
||||
```
|
||||
|
||||
# JSON Patches
|
||||
|
||||
- use JSON Patch to describe edit operations
|
||||
- create diffs from two JSON values
|
||||
- or use a JSON Merge Patch that looks like the document
|
||||
|
||||
```cpp
|
||||
json source = R"({"F": "Paris", "D": "Berlin"})"_json;
|
||||
|
||||
// a JSON Patch (RFC 6902)
|
||||
json p1 = R"([
|
||||
{"op": "add", "path": "/GB", "value": "London"}
|
||||
])"_json;
|
||||
json target = source.patch(p1);
|
||||
|
||||
// create a diff from two JSON values
|
||||
json p2 = json::diff(target, source);
|
||||
// [{"op": "remove", "path": "/GB"}]
|
||||
|
||||
// a JSON Merge Patch (RFC 7396)
|
||||
target.merge_patch(R"({"F": null})"_json);
|
||||
// {"D": "Berlin", "GB": "London"}
|
||||
```
|
||||
|
||||
# Binary formats
|
||||
|
||||
- compact binary representations
|
||||
- BJData, BON8, BSON, CBOR, MessagePack and UBJSON
|
||||
|
||||
```cpp
|
||||
// a JSON value
|
||||
json j = R"({"compact": true, "schema": 0})"_json;
|
||||
|
||||
// serialize to CBOR
|
||||
std::vector<std::uint8_t> v = json::to_cbor(j);
|
||||
// 0xA2, 0x67, 0x63, 0x6F, 0x6D, 0x70, 0x61,
|
||||
// 0x63, 0x74, 0xF5, 0x66, 0x73, 0x63, 0x68,
|
||||
// 0x65, 0x6D, 0x61, 0x00
|
||||
|
||||
// roundtrip
|
||||
json j_from_cbor = json::from_cbor(v);
|
||||
|
||||
// the same for the other formats
|
||||
auto b = json::to_bon8(j);
|
||||
auto m = json::to_msgpack(j);
|
||||
```
|
||||
|
||||
# Algorithms
|
||||
|
||||
- the standard algorithms just work
|
||||
- sort, find, count, merge and more
|
||||
|
||||
```cpp
|
||||
// sort JSON containers
|
||||
std::sort(j.begin(), j.end());
|
||||
|
||||
// find element
|
||||
auto pos = std::find(j.begin(), j.end(),
|
||||
json("needle"));
|
||||
|
||||
// count all numbers
|
||||
auto n = std::count_if(j.begin(), j.end(),
|
||||
[](const json& v) { return v.is_number(); });
|
||||
|
||||
// merge two sorted containers
|
||||
std::merge(j1.begin(), j1.end(),
|
||||
j2.begin(), j2.end(),
|
||||
std::back_inserter(j3));
|
||||
```
|
||||
|
||||
# Iterators
|
||||
|
||||
- iterators, const iterators, and reverse iterators
|
||||
- random access for arrays
|
||||
- items() gives you keys and values
|
||||
|
||||
```cpp
|
||||
json j = {1, 2, 3, 4, 5};
|
||||
|
||||
// range for
|
||||
for (auto& el : j)
|
||||
{
|
||||
// print all values
|
||||
std::cerr << el << '\n';
|
||||
}
|
||||
|
||||
// classical iterators
|
||||
for (auto it = j.begin(); it != j.end(); ++it)
|
||||
{
|
||||
// double all values
|
||||
*it = it->get<int>() * 2;
|
||||
}
|
||||
```
|
||||
|
||||
# Structured bindings
|
||||
|
||||
- since C++17, unpack keys and values with structured bindings
|
||||
|
||||
```cpp
|
||||
// JSON object
|
||||
auto j = R"({"foo": 23, "bar": 42})"_json;
|
||||
|
||||
// structured bindings
|
||||
for (auto& [key, val] : j.items())
|
||||
{
|
||||
std::cerr << key << ':' << val << '\n';
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user