1
0
mirror of https://github.com/nlohmann/json synced 2024-11-25 05:10:05 +00:00

Overwork documentation (#3444)

* 📝 overwork macro documentation

* 📝 address review comments

* 🔧 add style check to Makefile

* 🙈 overwork .gitignore

* 📌 Pygments 2.12.0 is broken

* ✏️ fix links

* 🚸 adjust output to cppcheck

* 📝 add titles to more admonitions

* ✏️ fix typos

* 📝 document future behavior change
This commit is contained in:
Niels Lohmann 2022-04-25 22:40:45 +02:00 committed by GitHub
parent fcc36f99ba
commit a6ee8bf9d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 1689 additions and 366 deletions

25
.gitignore vendored
View File

@ -1,32 +1,21 @@
json_unit
json_benchmarks
json_benchmarks_simple
fuzz-testing
*.dSYM
*.o
*.gcno
*.gcda
build
build_coverage
clang_analyze_build
benchmarks/files/numbers/*.json
.DS_Store
.wsjcpp-logs/*
.wsjcpp/*
.idea
/.idea
/cmake-build-*
test/test-*
/.vs
doc/html
doc/mkdocs/venv/
doc/mkdocs/docs/examples
doc/mkdocs/site
doc/mkdocs/docs/__pycache__/
/doc/mkdocs/docs/examples/
/doc/mkdocs/docs/__pycache__/
/doc/mkdocs/site/
/doc/mkdocs/venv/
/doc/docset/JSON_for_Modern_C++.docset/
/doc/docset/JSON_for_Modern_C++.tgz
/doc/mkdocs/docs/images/json.gif

View File

@ -93,7 +93,7 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t
## Examples
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
Beside the examples below, you may want to check the [documentation](https://json.nlohmann.me/) where each function contains a separate code example (e.g., check out [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
### JSON as first-class data type
@ -162,7 +162,7 @@ json j2 = {
};
```
Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help:
Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://json.nlohmann.me/api/basic_json/array/) and [`json::object()`](https://json.nlohmann.me/api/basic_json/object/) will help:
```cpp
// a way to express the empty array []
@ -197,7 +197,7 @@ auto j2 = R"(
Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object.
The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/):
The above example can also be expressed explicitly using [`json::parse()`](https://json.nlohmann.me/api/basic_json/parse/):
```cpp
// parse explicitly
@ -240,9 +240,9 @@ std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::
std::cout << j_string << " == " << serialized_string << std::endl;
```
[`.dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) returns the originally stored string value.
[`.dump()`](https://json.nlohmann.me/api/basic_json/dump/) returns the originally stored string value.
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
#### To/from streams (e.g. files, string streams)
@ -730,7 +730,7 @@ Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* In function `from_json`, use function [`at()`](https://json.nlohmann.me/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
#### Simplify your life with macros
@ -1647,7 +1647,7 @@ The library supports **Unicode input** as follows:
- [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library.
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
- To store wide strings (e.g., `std::wstring`), you need to convert them to a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling).
### Comments in JSON
@ -1682,7 +1682,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924).
### Further notes
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://json.nlohmann.me/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
- As the exact number type is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag.
- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824).

View File

@ -0,0 +1,59 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
nlohmann_json_t.name = nlohmann_json_j.at("name");
nlohmann_json_t.address = nlohmann_json_j.at("address");
nlohmann_json_t.age = nlohmann_json_j.at("age");
}
};
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,47 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, address, age)
};
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,54 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
person nlohmann_json_default_obj;
nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address);
nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age);
}
};
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,41 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person, name, address, age)
};
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,52 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name;
std::string address;
int age;
};
void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
nlohmann_json_t.name = nlohmann_json_j.at("name");
nlohmann_json_t.address = nlohmann_json_j.at("address");
nlohmann_json_t.age = nlohmann_json_j.at("age");
}
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,40 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name;
std::string address;
int age;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,52 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
};
void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
person nlohmann_json_default_obj;
nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address);
nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age);
}
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,39 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person, name, address, age)
} // namespace ns
int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,59 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
enum TaskState
{
TS_STOPPED,
TS_RUNNING,
TS_COMPLETED,
TS_INVALID = -1
};
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
{
{ TS_INVALID, nullptr },
{ TS_STOPPED, "stopped" },
{ TS_RUNNING, "running" },
{ TS_COMPLETED, "completed" }
})
enum class Color
{
red, green, blue, unknown
};
NLOHMANN_JSON_SERIALIZE_ENUM(Color,
{
{ Color::unknown, "unknown" }, { Color::red, "red" },
{ Color::green, "green" }, { Color::blue, "blue" }
})
} // namespace ns
int main()
{
// serialization
json j_stopped = ns::TS_STOPPED;
json j_red = ns::Color::red;
std::cout << "ns::TS_STOPPED -> " << j_stopped
<< ", ns::Color::red -> " << j_red << std::endl;
// deserialization
json j_running = "running";
json j_blue = "blue";
auto running = j_running.get<ns::TaskState>();
auto blue = j_blue.get<ns::Color>();
std::cout << j_running << " -> " << running
<< ", " << j_blue << " -> " << static_cast<int>(blue) << std::endl;
// deserializing undefined JSON value to enum
// (where the first map entry above is the default)
json j_pi = 3.14;
auto invalid = j_pi.get<ns::TaskState>();
auto unknown = j_pi.get<ns::Color>();
std::cout << j_pi << " -> " << invalid << ", "
<< j_pi << " -> " << static_cast<int>(unknown) << std::endl;
}

View File

@ -0,0 +1,3 @@
ns::TS_STOPPED -> "stopped", ns::Color::red -> "red"
"running" -> 1, "blue" -> 2
3.14 -> -1, 3.14 -> 3

View File

@ -0,0 +1,33 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
enum class Color
{
red, green, blue, unknown
};
NLOHMANN_JSON_SERIALIZE_ENUM(Color,
{
{ Color::unknown, "unknown" }, { Color::red, "red" },
{ Color::green, "green" }, { Color::blue, "blue" },
{ Color::red, "rot" } // a second conversion for Color::red
})
}
int main()
{
// serialization
json j_red = ns::Color::red;
std::cout << static_cast<int>(ns::Color::red) << " -> " << j_red << std::endl;
// deserialization
json j_rot = "rot";
auto rot = j_rot.get<ns::Color>();
auto red = j_red.get<ns::Color>();
std::cout << j_rot << " -> " << static_cast<int>(rot) << std::endl;
std::cout << j_red << " -> " << static_cast<int>(red) << std::endl;
}

View File

@ -0,0 +1,3 @@
0 -> "red"
"rot" -> 0
"red" -> 0

View File

@ -1,18 +1,21 @@
# serve the site locally
serve: prepare_files
serve: prepare_files style_check
venv/bin/mkdocs serve
build: prepare_files
serve_dirty: prepare_files style_check
venv/bin/mkdocs serve --dirtyreload
build: prepare_files style_check
venv/bin/mkdocs build
# create files that are not versioned inside the mkdocs folder
# create files that are not versioned inside the mkdocs folder (images, examples)
prepare_files: clean
# create subfolders
mkdir docs/examples
# copy images
cp -vr ../json.gif docs/images
# copy examples
cp -vr ../examples/*.cpp ../examples/*.output docs/examples
cp -r ../json.gif docs/images
cp -r ../examples/*.cpp ../examples/*.output docs/examples
style_check:
@cd docs ; python3 ../scripts/check_structure.py
# clean subfolders
clean:

View File

@ -35,9 +35,9 @@ Constant.
## Notes
!!! danger
!!! info "Precondition"
Calling `back` on an empty array or object is undefined behavior and is **guarded by an assertion**!
The array or object must not be empty. Calling `back` on an empty array or object yields undefined behavior.
## Examples

View File

@ -250,17 +250,15 @@ basic_json(basic_json&& other) noexcept;
!!! info "Preconditions"
- Iterators `first` and `last` must be initialized. **This precondition is enforced with an assertion (see
warning).** If assertions are switched off, a violation of this precondition yields undefined behavior.
- Iterators `first` and `last` must be initialized. **This precondition is enforced with a
[runtime assertion](../../features/assertions.md).
- Range `[first, last)` is valid. Usually, this precondition cannot be checked efficiently. Only certain edge
cases are detected; see the description of the exceptions above. A violation of this precondition yields
undefined behavior.
!!! warning
!!! danger "Runtime assertion"
A precondition is enforced with a runtime assertion that will result in calling `std::abort` if this
precondition is not met. Assertions can be disabled by defining `NDEBUG` at compile time. See
<https://en.cppreference.com/w/cpp/error/assert> for more information.
A precondition is enforced with a [runtime assertion](../../features/assertions.md).
- Overload 8:

View File

@ -28,9 +28,9 @@ Constant.
## Notes
!!! danger
!!! info "Precondition"
Calling `front` on an empty array or object is undefined behavior and is **guarded by an assertion**!
The array or object must not be empty. Calling `front` on an empty array or object yields undefined behavior.
## Examples

View File

@ -90,7 +90,7 @@ Depends on what `json_serializer<ValueType>` `from_json()` method throws
## Notes
!!! warning
!!! danger "Undefined behavior"
Writing data to the pointee (overload 3) of the result yields an undefined state.

View File

@ -33,7 +33,7 @@ Constant.
## Notes
!!! warning
!!! danger "Undefined behavior"
Writing data to the pointee of the result yields an undefined state.

View File

@ -16,7 +16,7 @@ Implicit reference access to the internally stored JSON value. No copies are mad
: reference type; must be a reference to [`array_t`](array_t.md), [`object_t`](object_t.md),
[`string_t`](string_t.md), [`boolean_t`](boolean_t.md), [`number_integer_t`](number_integer_t.md), or
[`number_unsigned_t`](number_unsigned_t.md), [`number_float_t`](number_float_t.md), or [`binary_t`](binary_t.md).
Enforced by static assertion.
Enforced by a static assertion.
## Return value
@ -38,7 +38,7 @@ Constant.
## Notes
!!! warning
!!! danger "Undefined behavior"
Writing data to the referee of the result yields an undefined state.

View File

@ -292,7 +292,7 @@ Access to the JSON value
- [**std::hash&lt;basic_json&gt;**](std_hash.md) - return a hash value for a JSON object
- [**std::swap&lt;basic_json&gt;**](std_swap.md) - exchanges the values of two JSON objects
## Example
## Examples
??? example

View File

@ -24,7 +24,7 @@ Constant.
## Notes
!!! note
!!! note "Comparisons"
Discarded values are never compared equal with [`operator==`](operator_eq.md). That is, checking whether a JSON
value `j` is discarded will only work via:
@ -41,7 +41,7 @@ Constant.
will always be `#!cpp false`.
!!! note
!!! note "Removal during parsing with callback functions"
When a value is discarded by a callback function (see [`parser_callback_t`](parser_callback_t.md)) during parsing,
then it is removed when it is part of a structured value. For instance, if the second value of an array is discarded,

View File

@ -63,7 +63,7 @@ Constant.
When iterating over an array, `key()` will return the index of the element as string (see example). For primitive types
(e.g., numbers), `key()` returns an empty string.
!!! warning
!!! danger "Lifetime issues"
Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See
<https://github.com/nlohmann/json/issues/2040> for more information.

View File

@ -45,6 +45,10 @@ Constant.
--8<-- "examples/meta.output"
```
## See also
- [**NLOHMANN_JSON_VERSION_MAJOR**/**NLOHMANN_JSON_VERSION_MINOR**/**NLOHMANN_JSON_VERSION_PATCH**](../macros/nlohmann_json_version_major.md) - library version information
## Version history
- Added in version 2.1.0.

View File

@ -8,7 +8,7 @@ using object_comparator_t = std::less<>; // since C++14
The comparator used in [`object_t`](object_t.md).
When C++14 is detected, a transparent com parator is used which, when combined with perfect forwarding on find() and
When C++14 is detected, a transparent comparator is used which, when combined with perfect forwarding on find() and
count() calls, prevents unnecessary string construction.
## Version history

View File

@ -74,10 +74,11 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Notes
!!! danger
!!! danger "Undefined behavior and runtime assertions"
1. If the element with key `idx` does not exist, the behavior is undefined.
2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by an assertion**!
2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by a
[runtime assertion](../../features/assertions.md)**!
1. The non-const version may add values: If `idx` is beyond the range of the array (i.e., `idx >= size()`), then the
array is silently filled up with `#!json null` values to make `idx` a valid reference to the last stored element. In

View File

@ -27,33 +27,44 @@ Linear in the size of the JSON value.
## Notes
By default `JSON_EXPLICIT` defined to the empty string, so the signature is:
!!! note "Definition of `JSON_EXPLICIT`"
```cpp
template<typename ValueType>
operator ValueType() const;
```
By default `JSON_EXPLICIT` is defined to the empty string, so the signature is:
If [`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) is set to `0`,
`JSON_EXPLICIT` is defined to `#!cpp explicit`:
```cpp
template<typename ValueType>
operator ValueType() const;
```
```cpp
template<typename ValueType>
explicit operator ValueType() const;
```
If [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) is set to `0`,
`JSON_EXPLICIT` is defined to `#!cpp explicit`:
```cpp
template<typename ValueType>
explicit operator ValueType() const;
```
That is, implicit conversions can be switched off by defining
[`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0`.
!!! info "Future behavior change"
Implicit conversions will be switched off by default in the next major release of the library. That is,
`JSON_EXPLICIT` will be set to `#!cpp explicit` by default.
You can prepare existing code by already defining
[`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0` and replace any implicit
conversions with calls to [`get`](../basic_json/get.md).
That is, implicit conversions can be switched off by defining
[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) to `0`.
## Examples
??? example
The example below shows several conversions from JSON values
to other types. There a few things to note: (1) Floating-point numbers can
be converted to integers, (2) A JSON array can be converted to a standard
`std::vector<short>`, (3) A JSON object can be converted to C++
associative containers such as `std::unordered_map<std::string, json>`.
The example below shows several conversions from JSON values to other types. There are a few things to note: (1)
Floating-point numbers can be converted to integers, (2) A JSON array can be converted to a standard
`std::vector<short>`, (3) A JSON object can be converted to C++ associative containers such as
`std::unordered_map<std::string, json>`.
```cpp
--8<-- "examples/operator__ValueType.cpp"

View File

@ -36,7 +36,7 @@ ValueType value(const json_pointer& ptr,
}
```
!!! note
!!! note "Differences to `at` and `operator[]`"
- Unlike [`at`](at.md), this function does not throw if the given `key`/`ptr` was not found.
- Unlike [`operator[]`](operator[].md), this function does not implicitly add an element to the position defined by

View File

@ -16,7 +16,13 @@ are the base for JSON patches.
## Notes
For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is deprecated and may be removed in a future major version.
For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) in
which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is deprecated
and may be removed in a future major version.
## Member types
- [**string_t**](string_t.md) - the string type used for the reference tokens
## Member functions
@ -31,10 +37,6 @@ For backwards compatibility `RefStringType` may also be a specialization of [`ba
- [**push_back**](push_back.md) - append an unescaped token at the end of the pointer
- [**empty**](empty.md) - return whether pointer points to the root document
## Member types
- [**string_t**](string_t.md) - the string type used for the reference tokens
## See also
- [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers

View File

@ -1,22 +1,37 @@
# Macros
!!! note
Some aspects of the library can be configured by defining preprocessor macros **before** including the `json.hpp`
header. See also the [macro overview page](../../features/macros.md).
This page is under construction. See the [macro overview page](../../features/macros.md) until then.
## Runtime assertions
Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header.
- [**JSON_ASSERT(x)**](json_assert.md) - control behavior of runtime assertions
- [`JSON_ASSERT(x)`](json_assert.md)
- `JSON_CATCH_USER(exception)`
- `JSON_DIAGNOSTICS`
- `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20`
- `JSON_NOEXCEPTION`
- `JSON_NO_IO`
- `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
- `JSON_THROW_USER(exception)`
- `JSON_TRY_USER`
- `JSON_USE_IMPLICIT_CONVERSIONS`
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
- `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
- `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH`
## Exceptions
- [**JSON_CATCH_USER(exception)**<br>**JSON_THROW_USER(exception)**<br>**JSON_TRY_USER**](json_throw_user.md) - control exceptions
- [**JSON_DIAGNOSTICS**](json_diagnostics.md) - control extended diagnostics
- [**JSON_NOEXCEPTION**](json_noexception.md) - switch off exceptions
## Language support
- [**JSON_HAS_CPP_11**<br>**JSON_HAS_CPP_14**<br>**JSON_HAS_CPP_17**<br>**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard
- [**JSON_HAS_FILESYSTEM**<br>**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
## Library version
- [**JSON_SKIP_LIBRARY_VERSION_CHECK**](json_skip_library_version_check.md) - skip library version check
- [**NLOHMANN_JSON_VERSION_MAJOR**<br>**NLOHMANN_JSON_VERSION_MINOR**<br>**NLOHMANN_JSON_VERSION_PATCH**](nlohmann_json_version_major.md) - library version information
## Type conversions
- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions
## Serialization/deserialization macros
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_intrusive.md) - serialization/deserialization of types _with_ access to private variables
- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_non_intrusive.md) - serialization/deserialization of types _without_ access to private variables
- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum
types

View File

@ -1,11 +1,84 @@
# JSON_ASSERT(x)
# JSON_ASSERT
```cpp
JSON_ASSERT(x)
#define JSON_ASSERT(x) /* value */
```
## Default implementation
This macro controls which code is executed for [runtime assertions](../../features/assertions.md) of the library.
## Parameters
`x` (in)
: expression of scalar type
## Default definition
The default value is [`#!cpp assert(x)`](https://en.cppreference.com/w/cpp/error/assert).
```cpp
assert(x);
#define JSON_ASSERT(x) assert(x)
```
Therefore, assertions can be switched off by defining `NDEBUG`.
## Notes
- The library uses numerous assertions to guarantee invariants and to abort in case of otherwise undefined behavior
(e.g., when calling [operator[]](../basic_json/operator%5B%5D.md) with a missing object key on a `const` object). See
page [runtime assertions](../../features/assertions.md) for more information.
- Defining the macro to code that does not call `std::abort` may leave the library in an undefined state.
- The macro is undefined outside the library.
## Examples
??? example "Example 1: default behavior"
The following code will trigger an assertion at runtime:
```cpp
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
const json j = {{"key", "value"}};
auto v = j["missing"];
}
```
Output:
```
Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144.
```
??? example "Example 2: user-defined behavior"
The assertion reporting can be changed by defining `JSON_ASSERT(x)` differently.
```cpp
#include <cstdio>
#include <cstdlib>
#define JSON_ASSERT(x) if(!(x)){fprintf(stderr, "assertion error in %s\n", __FUNCTION__); std::abort();}
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
const json j = {{"key", "value"}};
auto v = j["missing"];
}
```
Output:
```
assertion error in operator[]
```
## Version history
- Added in version 3.9.0.

View File

@ -0,0 +1,67 @@
# JSON_DIAGNOSTICS
```cpp
#define JSON_DIAGNOSTICS /* value */
```
This macro enables [extended diagnostics for exception messages](../../home/exceptions.md#extended-diagnostic-messages).
Possible values are `1` to enable or `0` to disable (default).
When enabled, exception messages contain a [JSON Pointer](../json_pointer/json_pointer.md) to the JSON value that
triggered the exception. Note that enabling this macro increases the size of every JSON value by one pointer and adds
some runtime overhead.
The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets
`JSON_DIAGNOSTICS` accordingly.
## Default definition
The default value is `0` (extended diagnostics are switched off).
```cpp
#define JSON_DIAGNOSTICS 0
```
When the macro is not defined, the library will define it to its default value.
## Notes
!!! danger "ABI incompatibility"
As this macro changes the definition of the `basic_json` object, it MUST be defined in the same way globally, even
across different compilation units: `basic_json` objects with differently defined `JSON_DIAGNOSTICS` macros are
not compatible!
## Examples
??? example "Example 1: default behavior"
```cpp
--8<-- "examples/diagnostics_standard.cpp"
```
Output:
```
--8<-- "examples/diagnostics_standard.output"
```
This exception can be hard to debug if storing the value `#!c "12"` and accessing it is further apart.
??? example "Example 2: extended diagnostic messages"
```cpp
--8<-- "examples/diagnostics_extended.cpp"
```
Output:
```
--8<-- "examples/diagnostics_extended.output"
```
Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type.
## Version history
- Added in version 3.10.0.

View File

@ -0,0 +1,28 @@
# JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20
```cpp
#define JSON_HAS_CPP_11
#define JSON_HAS_CPP_14
#define JSON_HAS_CPP_17
#define JSON_HAS_CPP_20
```
The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view`
support for C++17). For these new features, the library implements some preprocessor checks to determine the C++
standard. By defining any of these symbols, the internal check is overridden and the provided C++ version is
unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be
detected incorrectly.
## Default definition
The default value is detected based on preprocessor macros such as `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or
`#!cpp _MSVC_LANG`.
## Notes
- `#!cpp JSON_HAS_CPP_11` is always defined.
- All macros are undefined outside the library.
## Version history
- Added in version 3.10.5.

View File

@ -0,0 +1,30 @@
# JSON_HAS_FILESYSTEM / JSON_HAS_EXPERIMENTAL_FILESYSTEM
```cpp
#define JSON_HAS_FILESYSTEM /* value */
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM /* value */
```
When compiling with C++17, the library provides conversions from and to
[`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path). As compiler support for filesystem is
limited, the library tries to detect whether
[`<filesystem>`/`std::filesystem`](https://en.cppreference.com/w/cpp/header/filesystem) (`JSON_HAS_FILESYSTEM`) or
[`<experimental/filesystem>`/`std::experimental::filesystem`](https://en.cppreference.com/w/cpp/header/experimental/filesystem)
(`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used. To override the built-in check, define `JSON_HAS_FILESYSTEM` or
`JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`.
## Default definition
The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_filesystem`,
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
`#!cpp __has_include(<experimental/filesystem>)`.
## Notes
- Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for
filesystem support.
- Both macros are undefined outside the library.
## Version history
- Added in version 3.10.5.

View File

@ -0,0 +1,21 @@
# JSON_NO_IO
```cpp
#define JSON_NO_IO
```
When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
relying on these headers are excluded. This is relevant for environments where these I/O functions are disallowed for
security reasons (e.g., Intel Software Guard Extensions (SGX)).
## Default definition
By default, `#!cpp JSON_NO_IO` is not defined.
```cpp
#undef JSON_NO_IO
```
## Version history
- Added in version 3.10.0.

View File

@ -0,0 +1,32 @@
# JSON_NOEXCEPTION
```cpp
#define JSON_NOEXCEPTION
```
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try`
is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by
`#!cpp std::abort()`.
The same effect is achieved by setting the compiler flag `-fno-exceptions`.
## Default definition
By default, the macro is not defined.
```cpp
#undef JSON_NOEXCEPTION
```
## Notes
The explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not
available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824).
## See also
- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions
## Version history
Added in version 2.1.0.

View File

@ -0,0 +1,37 @@
# JSON_SKIP_LIBRARY_VERSION_CHECK
```cpp
#define JSON_SKIP_LIBRARY_VERSION_CHECK
```
When defined, the library will not create a compiler warning when a different version of the library was already
included.
## Default definition
By default, the macro is not defined.
```cpp
#undef JSON_SKIP_LIBRARY_VERSION_CHECK
```
## Notes
!!! danger "ABI compatibility"
Mixing different library versions in the same code can be a problem as the different versions may not be ABI
compatible.
## Examples
!!! example
The following warning will be shown in case a different version of the library was already included:
```
Already included a different version of the library!
```
## Version history
Added in version 3.11.0.

View File

@ -0,0 +1,20 @@
# JSON_SKIP_UNSUPPORTED_COMPILER_CHECK
```cpp
#define JSON_SKIP_UNSUPPORTED_COMPILER_CHECK
```
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to
use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
## Default definition
By default, the macro is not defined.
```cpp
#undef JSON_SKIP_UNSUPPORTED_COMPILER_CHECK
```
## Version history
Added in version 3.2.0.

View File

@ -0,0 +1,75 @@
# JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER
```cpp
// (1)
#define JSON_CATCH_USER(exception) /* value */
// (2)
#define JSON_THROW_USER(exception) /* value */
// (3)
#define JSON_TRY_USER /* value */
```
Controls how exceptions are handled by the library.
1. This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library.
The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range`
exceptions internally to rethrow them as [`json::out_of_range`](../../home/exceptions.md#out-of-range) exceptions.
The macro is always followed by a scope.
2. This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that
`JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield
undefined behavior.
3. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
## Parameters
`exception` (in)
: an exception type
## Default definition
By default, the macros map to their respective C++ keywords:
```cpp
#define JSON_CATCH_USER(exception) catch(exception)
#define JSON_THROW_USER(exception) throw exception
#define JSON_TRY_USER try
```
When exceptions are switched off, the `#!cpp try` block is executed unconditionally, and throwing exceptions is
replaced by calling [`std::abort`](https://en.cppreference.com/w/cpp/utility/program/abort) to make reaching the
`#!cpp throw` branch abort the process.
```cpp
#define JSON_THROW_USER(exception) std::abort()
#define JSON_TRY_USER if (true)
#define JSON_CATCH_USER(exception) if (false)
```
## Examples
??? example
The code below switches off exceptions and creates a log entry with a detailed error message in case of errors.
```cpp
#include <iostream>
#define JSON_TRY_USER if(true)
#define JSON_CATCH_USER(exception) if(false)
#define JSON_THROW_USER(exception) \
{std::clog << "Error in " << __FILE__ << ":" << __LINE__ \
<< " (function " << __FUNCTION__ << ") - " \
<< (exception).what() << std::endl; \
std::abort();}
#include <nlohmann/json.hpp>
```
## See also
- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions
- [JSON_NOEXCEPTION](JSON_NOEXCEPTION) - switch off exceptions
## Version history
- Added in version 3.1.0.

View File

@ -0,0 +1,56 @@
# JSON_USE_IMPLICIT_CONVERSIONS
```cpp
#define JSON_USE_IMPLICIT_CONVERSIONS /* value */
```
When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. The
value directly affects [`operator ValueType`](../basic_json/operator_ValueType.md).
Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which
sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly.
## Default definition
By default, implicit conversions are enabled.
```cpp
#define JSON_USE_IMPLICIT_CONVERSIONS 1
```
## Notes
!!! info "Future behavior change"
Implicit conversions will be switched off by default in the next major release of the library.
You can prepare existing code by already defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` and replace any implicit
conversions with calls to [`get`](../basic_json/get.md).
## Examples
??? example
This is an example for an implicit conversion:
```cpp
json j = "Hello, world!";
std::string s = j;
```
When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be
written like this:
```cpp
json j = "Hello, world!";
auto s = j.get<std::string>();
```
## See also
- [**operator ValueType**](../basic_json/operator_ValueType.md) - get a value (implicit)
- [**get**](../basic_json/get.md) - get a value (explicit)
## Version history
- Added in version 3.9.0.

View File

@ -0,0 +1,124 @@
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
```cpp
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
```
These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
serialization and want to use the member variable names as object keys in that object. The macro is to be defined
**inside** the class/struct to create code for.
Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md), it can access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members.
1. Will use [`at`](../basic_json/at.md) during deserialization and will throw
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object.
2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
default constructs an object and uses its values as the defaults when calling the `value` function.
## Parameters
`type` (in)
: name of the type (class, struct) to serialize/deserialize
`member` (in)
: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list
## Default definition
The macros add two friend functions to the class which take care of the serialization and deserialization:
```cpp
friend void to_json(nlohmann::json&, const type&);
friend void from_json(const nlohmann::json&, type&);
```
See examples below for the concrete generated code.
## Notes
!!! info "Prerequisites"
1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types)
for how to overcome this limitation.
2. The macro must be used inside the type (class/struct).
!!! warning "Implementation limits"
- The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types
with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually.
- The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as
[`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported.
## Examples
??? example "Example (1): NLOHMANN_DEFINE_TYPE_INTRUSIVE"
Consider the following complete example:
```cpp hl_lines="21"
--8<-- "examples/nlohmann_define_type_intrusive_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_intrusive_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE` applicable, but not
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`.
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is used _inside_ the class.
- A missing key "age" in the deserialization yields an exception. To fall back to the default value,
`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` can be used.
The macro is equivalent to:
```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33"
--8<-- "examples/nlohmann_define_type_intrusive_explicit.cpp"
```
??? example "Example (2): NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT"
Consider the following complete example:
```cpp hl_lines="21"
--8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` applicable,
but not `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` is used _inside_ the class.
- A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used.
The macro is equivalent to:
```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34"
--8<-- "examples/nlohmann_define_type_intrusive_with_default_explicit.cpp"
```
Note how a default-initialized `person` object is used in the `from_json` to fill missing values.
## See also
- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md)
for a similar macro that can be defined _outside_ the type.
- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview.
## Version history
1. Added in version 3.9.0.
2. Added in version 3.11.0.

View File

@ -0,0 +1,124 @@
# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
```cpp
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
```
These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
serialization and want to use the member variable names as object keys in that object. The macro is to be defined
**outside** the class/struct to create code for, but **inside** its namespace.
Unlike [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), it **cannot** access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members.
1. Will use [`at`](../basic_json/at.md) during deserialization and will throw
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object.
2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
default constructs an object and uses its values as the defaults when calling the `value` function.
## Parameters
`type` (in)
: name of the type (class, struct) to serialize/deserialize
`member` (in)
: name of the (public) member variable to serialize/deserialize; up to 64 members can be given as comma-separated list
## Default definition
The macros add two functions to the namespace which take care of the serialization and deserialization:
```cpp
void to_json(nlohmann::json&, const type&);
void from_json(const nlohmann::json&, type&);
```
See examples below for the concrete generated code.
## Notes
!!! info "Prerequisites"
1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types)
for how to overcome this limitation.
2. The macro must be used outside the type (class/struct).
3. The passed members must be public.
!!! warning "Implementation limits"
- The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types
with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually.
- The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as
[`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported.
## Examples
??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE"
Consider the following complete example:
```cpp hl_lines="15"
--8<-- "examples/nlohmann_define_type_non_intrusive_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_non_intrusive_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` applicable.
- The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` is used _outside_ the class, but _inside_ its namespace `ns`.
- A missing key "age" in the deserialization yields an exception. To fall back to the default value,
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` can be used.
The macro is equivalent to:
```cpp hl_lines="15 16 17 18 19 20 21 22 23 24 25 26 27"
--8<-- "examples/nlohmann_define_type_non_intrusive_explicit.cpp"
```
??? example "Example (2): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT"
Consider the following complete example:
```cpp hl_lines="20"
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`
applicable.
- The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` is used _outside_ the class, but _inside_ its namespace `ns`.
- A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used.
The macro is equivalent to:
```cpp hl_lines="20 21 22 23 24 25 26 27 28 29 30 31 32 33"
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp"
```
Note how a default-initialized `person` object is used in the `from_json` to fill missing values.
## See also
- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md)
for a similar macro that can be defined _inside_ the type.
- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview.
## Version history
1. Added in version 3.9.0.
2. Added in version 3.11.0.

View File

@ -0,0 +1,84 @@
# NLOHMANN_JSON_SERIALIZE_ENUM
```cpp
#define NLOHMANN_JSON_SERIALIZE_ENUM(type, conversion...)
```
By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an
enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be
undefined or a different enum value than was originally intended.
The `NLOHMANN_JSON_SERIALIZE_ENUM` allows to define a user-defined serialization for every enumerator.
## Parameters
`type` (in)
: name of the enum to serialize/deserialize
`conversion` (in)
: a pair of an enumerator and a JSON serialization; arbitrary pairs can can be given as comma-separated list
## Default definition
The macros add two friend functions to the class which take care of the serialization and deserialization:
```cpp
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const type& e);
template<typename BasicJsonType>
inline void from_json(const BasicJsonType& j, type& e);
```
## Notes
!!! info "Prerequisites"
The macro must be used inside the namespace of the enum.
!!! important "Important notes"
- When using [`get<ENUM_TYPE>()`](../basic_json/get.md), undefined JSON values will default to the first specified
conversion. Select this default pair carefully. See example 1 below.
- If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the
list will be returned when converting to or from JSON. See example 2 below.
## Examples
??? example "Example 1: Basic usage"
The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM` can be used to serialize/deserialize both classical enums and
C++11 enum classes:
```cpp hl_lines="16 17 18 19 20 21 22 29 30 31 32 33"
--8<-- "examples/nlohmann_json_serialize_enum.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_json_serialize_enum.output"
```
??? example "Example 2: Multiple conversions for one enumerator"
The example shows how to use multiple conversions for a single enumerator. In the example, `Color::red` will always
be *serialized* to `"red"`, because the first occurring conversion. The second conversion, however, offers an
alternative *deserialization* from `"rot"` to `Color::red`.
```cpp hl_lines="17"
--8<-- "examples/nlohmann_json_serialize_enum_2.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_json_serialize_enum_2.output"
```
## See also
- [Specializing enum conversion](../../features/enum_conversion.md)
## Version history
Added in version 3.4.0.

View File

@ -0,0 +1,23 @@
# NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH
```cpp
#define NLOHMANN_JSON_VERSION_MAJOR /* value */
#define NLOHMANN_JSON_VERSION_MINOR /* value */
#define NLOHMANN_JSON_VERSION_PATCH /* value */
```
These macros are defined by the library and contain the version numbers according to
[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
## Default definition
The macros are defined according to the current library version.
## See also
- [meta](../basic_json/meta.md) - returns version information on the library
- [JSON_SKIP_LIBRARY_VERSION_CHECK](json_skip_library_version_check.md) - skip library version check
## Version history
- Added in version 3.1.0.

View File

@ -77,7 +77,7 @@ Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* In function `from_json`, use function [`at()`](../api/basic_json/at.md) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
@ -87,16 +87,19 @@ If you just want to serialize/deserialize some structs, the `to_json`/`from_json
There are four macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](macros.md#nlohmann_define_type_intrusivetype-member).
!!! note
!!! info "Implementation limits"
At most 64 member variables can be passed to these macros.
- The current macro implementations are limited to at most 64 member variables. If you want to serialize/deserialize
types with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually.
- The macros only work for the [`nlohmann::json`](../api/json.md) type; other specializations such as
[`nlohmann::ordered_json`](../api/ordered_json.md) are currently unsupported.
??? example

View File

@ -0,0 +1,104 @@
# Runtime Assertions
The code contains numerous debug assertions to ensure class invariants are valid or to detect undefined behavior.
Whereas the former class invariants are nothing to be concerned of, the latter checks for undefined behavior are to
detect bugs in client code.
## Switch off runtime assertions
Runtime assertions can be switched off by defining the preprocessor macro `NDEBUG` (see the
[documentation of assert](https://en.cppreference.com/w/cpp/error/assert)) which is the default for release builds.
## Change assertion behavior
The behavior of runtime assertions can be changes by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md)
before including the `json.hpp` header.
## Function with runtime assertions
### Unchecked object access to a const value
Function [`operator[]`](../api/basic_json/operator%5B%5D.md) implements unchecked access for objects. Whereas a missing
key is added in case of non-const objects, accessing a const object with a missing key is undefined behavior (think of a
dereferenced null pointer) and yields a runtime assertion.
If you are not sure whether an element in an object exists, use checked access with the
[`at` function](../api/basic_json/at.md) or call the [`contains` function](../api/basic_json/contains.md) before.
See also the documentation on [element access](element_access/index.md).
??? example "Example 1: Missing object key"
The following code will trigger an assertion at runtime:
```cpp
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
const json j = {{"key", "value"}};
auto v = j["missing"];
}
```
Output:
```
Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144.
```
### Constructing from an uninitialized iterator range
Constructing a JSON value from an iterator range (see [constructor](../api/basic_json/basic_json.md)) with an
uninitialized iterator is undefined behavior and yields a runtime assertion.
??? example "Example 2: Uninitialized iterator range"
The following code will trigger an assertion at runtime:
```cpp
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
json::iterator it1, it2;
json j(it1, it2);
}
```
Output:
```
Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368.
```
### Operations on uninitialized iterators
Any operation on uninitialized iterators (i.e., iterators that are not associated with any JSON value) is undefined
behavior and yields a runtime assertion.
??? example "Example 3: Uninitialized iterator"
The following code will trigger an assertion at runtime:
```cpp
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
json::iterator it;
++it;
}
```
Output:
```
Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368.
```

View File

@ -94,9 +94,9 @@ When accessing an invalid index (i.e., an index greater than or equal to the arr
## Summary
| scenario | non-const value | const value |
|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|
| access to existing object key | reference to existing value is returned | const reference to existing value is returned |
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; assertion in debug mode |
| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; assertion in debug mode |
| scenario | non-const value | const value |
|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| access to existing object key | reference to existing value is returned | const reference to existing value is returned |
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode |
| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode |

View File

@ -24,8 +24,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, {
})
```
The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState`
while avoiding repetition and boilerplate serialization code.
The [`NLOHMANN_JSON_SERIALIZE_ENUM()` macro](../api/macros/nlohmann_json_serialize_enum.md) declares a set of
`to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code.
## Usage
@ -45,10 +45,11 @@ assert(jPi.get<TaskState>() == TS_INVALID );
## Notes
Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above,
Just as in [Arbitrary Type Conversions](arbitrary_types.md) above,
- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace),
or the library will not be able to locate it, and it will default to integer serialization.
- [`NLOHMANN_JSON_SERIALIZE_ENUM()`](../api/macros/nlohmann_json_serialize_enum.md) MUST be declared in your enum type's
namespace (which can be the global namespace), or the library will not be able to locate it, and it will default to
integer serialization.
- It MUST be available (e.g., proper headers must be included) everywhere you use the conversions.
Other Important points:

View File

@ -1,47 +1,19 @@
# Supported Macros
Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header.
See also the [API documentation for macros](../api/macros/index.md) for examples and more information.
## `JSON_ASSERT(x)`
This macro controls which code is executed for runtime assertions of the libraries.
This macro controls which code is executed for [runtime assertions](assertions.md) of the library.
!!! info "Default behavior"
The default value is [`#!cpp assert(x)`](https://en.cppreference.com/w/cpp/error/assert).
```cpp
#define JSON_ASSERT(x) assert(x)
```
The macro was introduced in version 3.9.0.
See [full documentation of `JSON_ASSERT(x)`](../api/macros/json_assert.md).
## `JSON_CATCH_USER(exception)`
This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library.
The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range`
exceptions internally to rethrow them as [`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The
macro is always followed by a scope.
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp catch(exception)`](https://en.cppreference.com/w/cpp/language/try_catch).
```cpp
#define JSON_CATCH_USER(exception) catch(exception)
```
When exceptions are switched off by the compiler, the default value is `#!cpp if (false)` to make the catch block
unreachable.
```cpp
#define JSON_CATCH_USER(exception) if (false)
```
The macro was introduced in version 3.1.0.
See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md).
## `JSON_DIAGNOSTICS`
@ -55,19 +27,7 @@ that enabling this macro increases the size of every JSON value by one pointer a
The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets
`JSON_DIAGNOSTICS` accordingly.
!!! warning
As this macro changes the definition of the `basic_json` object, it MUST be defined in the same way globally, even
across different compilation units; DO NOT link together code compiled with different definitions of
`JSON_DIAGNOSTICS` as this is a violation of the One Definition Rule and will cause undefined behaviour.
!!! info "Default behavior"
```cpp
#define JSON_DIAGNOSTICS 0
```
The macro was introduced in version 3.10.0.
See [full documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md).
## `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20`
@ -77,12 +37,7 @@ standard. By defining any of these symbols, the internal check is overridden and
unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be
detected incorrectly.
!!! info "Default behavior"
The default value is detected based on the preprocessor macros `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or
`#!cpp _MSVC_LANG`.
The macros were introduced in version 3.10.5.
See [full documentation of `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, and `JSON_HAS_CPP_20`](../api/macros/json_has_cpp_11.md).
## `JSON_HAS_FILESYSTEM`, `JSON_HAS_EXPERIMENTAL_FILESYSTEM`
@ -91,37 +46,13 @@ for filesystem is limited, the library tries to detect whether `<filesystem>`/`s
or `<experimental/filesystem>`/`std::experimental::filesystem` (`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used.
To override the built-in check, define `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`.
!!! info "Default behavior"
The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_filesystem`,
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
`#!cpp __has_include(<experimental/filesystem>)`.
Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for
filesystem support.
The macros were introduced in version 3.10.5.
See [full documentation of `JSON_HAS_FILESYSTEM` and `JSON_HAS_EXPERIMENTAL_FILESYSTEM`](../api/macros/json_has_filesystem.md).
## `JSON_NOEXCEPTION`
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try`
is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by
`#!cpp std::abort()`.
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_NOEXCEPTION
```
The same effect is achieved by setting the compiler flag `-fno-exceptions`.
Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not
available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824).
The macro was introduced in version 2.1.0.
See [full documentation of `JSON_NOEXCEPTION`](../api/macros/json_noexception.md).
## `JSON_NO_IO`
@ -129,128 +60,39 @@ When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostrea
relying on these headers are excluded. This is relevant for environment where these I/O functions are disallowed for
security reasons (e.g., Intel Software Guard Extensions (SGX)).
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_NO_IO
```
The macro was introduced in version 3.10.0.
See [full documentation of `JSON_NO_IO`](../api/macros/json_no_io.md).
## `JSON_SKIP_LIBRARY_VERSION_CHECK`
When defined, the library will not create a compiler warning when a different version of the library was already
included.
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_SKIP_LIBRARY_VERSION_CHECK
```
The macro was introduced in version 3.11.0.
See [full documentation of `JSON_SKIP_LIBRARY_VERSION_CHECK`](../api/macros/json_skip_library_version_check.md).
## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to
use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_SKIP_UNSUPPORTED_COMPILER_CHECK
```
The macro was introduced in version 3.2.0.
See [full documentation of `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`](../api/macros/json_skip_unsupported_compiler_check.md).
## `JSON_THROW_USER(exception)`
This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that
`JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield
undefined behavior.
This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp throw exception`](https://en.cppreference.com/w/cpp/language/throw).
```cpp
#define JSON_THROW_USER(exception) throw exception
```
When exceptions are switched off by the compiler, the default value is
[`#!cpp std::abort()`](https://en.cppreference.com/w/cpp/utility/program/abort) to make reaching the throw branch
abort the process.
```cpp
#define JSON_THROW_USER(exception) std::abort()
```
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
The macro was introduced in version 3.1.0.
See [full documentation of `JSON_THROW_USER(exception)`](../api/macros/json_throw_user.md).
## `JSON_TRY_USER`
This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
This macro overrides `#!cpp try` calls inside the library.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp try`](https://en.cppreference.com/w/cpp/language/try_catch).
```cpp
#define JSON_TRY_USER try
```
When exceptions are switched off by the compiler, the default value is `#!cpp if (true)` to unconditionally execute
the following code block.
```cpp
#define JSON_TRY_USER if (true)
```
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
The macro was introduced in version 3.1.0.
See [full documentation of `JSON_TRY_USER`](../api/macros/json_throw_user.md).
## `JSON_USE_IMPLICIT_CONVERSIONS`
When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on.
??? example
This is an example for an implicit conversion:
```cpp
json j = "Hello, world!";
std::string s = j;
```
When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be
written like this:
```cpp
json j = "Hello, world!";
auto s = j.get<std::string>();
```
Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which
sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly.
!!! info "Default behavior"
```cpp
#define JSON_USE_IMPLICIT_CONVERSIONS 1
```
The macro was introduced in version 3.9.0.
See [full documentation of `JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md).
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
@ -261,18 +103,15 @@ The macro is to be defined inside the class/struct to create code for. Unlike
[`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members.
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
The macro was introduced in version 3.9.0.
See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE`](../api/macros/nlohmann_define_type_intrusive.md).
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)`
This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a
missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the
type be default constructible. The `from_json()` function default constructs an object and uses its values as the
defaults when calling the `value()` function.
missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs
an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function.
The macro was introduced in version 3.11.0.
See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_intrusive.md).
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
@ -283,29 +122,26 @@ The macro is to be defined inside the namespace of the class/struct to create co
accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The
first parameter is the name of the class/struct, and all remaining parameters name the members.
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
The macro was introduced in version 3.9.0.
See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](../api/macros/nlohmann_define_type_non_intrusive.md).
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)`
This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a
missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the
type be default constructible. The `from_json()` function default constructs an object and uses its values as the
defaults when calling the `value()` function.
missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs
an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function.
The macro was introduced in version 3.11.0.
See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_non_intrusive.md).
## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
This macro simplifies the serialization/deserialization of enum types. See
[Specializing enum conversion](enum_conversion.md) for more information.
The macro was introduced in version 3.4.0.
See [full documentation of `NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md).
## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH`
These macros are defined by the library and contain the version numbers according to
[Semantic Versioning 2.0.0](https://semver.org).
[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
The macros were introduced in version 3.1.0.
See [full documentation of `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and `NLOHMANN_JSON_VERSION_PATCH`](../api/macros/nlohmann_json_version_major.md).

View File

@ -275,7 +275,7 @@ The rationale is twofold:
### Determine number types
As the example in [Number conversion](#number_conversion) shows, there are different functions to determine the type of
As the example in [Number conversion](#number-conversion) shows, there are different functions to determine the type of
the stored number:
- [`is_number()`](../../api/basic_json/is_number.md) returns `#!c true` for any number type

View File

@ -28,9 +28,9 @@ class json::parse_error {
### Switch off exceptions
Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`).
Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol [`JSON_NOEXCEPTION`](../api/macros/json_noexception.md). In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`).
Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
Note that [`JSON_THROW_USER`](../api/macros/json_throw_user.md) should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
??? example
@ -52,6 +52,8 @@ Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or
Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824).
See [documentation of `JSON_TRY_USER`, `JSON_CATCH_USER` and `JSON_THROW_USER`](../api/macros/json_throw_user.md) for more information.
### Extended diagnostic messages
Exceptions in the library are thrown in the local context of the JSON value they are detected. This makes detailed diagnostics messages, and hence debugging, difficult.
@ -88,6 +90,7 @@ As this global context comes at the price of storing one additional pointer per
Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type.
See [documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) for more information.
## Parse errors

View File

@ -64,6 +64,7 @@ nav:
- features/parsing/parse_exceptions.md
- features/parsing/parser_callbacks.md
- features/parsing/sax_interface.md
- features/assertions.md
- features/enum_conversion.md
- features/macros.md
- Types:
@ -232,7 +233,30 @@ nav:
- 'ordered_map': api/ordered_map.md
- macros:
- 'Overview': api/macros/index.md
- 'JSON_ASSERT(x)': api/macros/json_assert.md
- 'JSON_ASSERT': api/macros/json_assert.md
- 'JSON_CATCH_USER': api/macros/json_throw_user.md
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
- 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md
- 'JSON_HAS_CPP_14': api/macros/json_has_cpp_11.md
- 'JSON_HAS_CPP_17': api/macros/json_has_cpp_11.md
- 'JSON_HAS_CPP_20': api/macros/json_has_cpp_11.md
- 'JSON_HAS_EXPERIMENTAL_FILESYSTEM': api/macros/json_has_filesystem.md
- 'JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
- 'JSON_NO_IO': api/macros/json_no_io.md
- 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md
- 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md
- 'JSON_THROW_USER': api/macros/json_throw_user.md
- 'JSON_TRY_USER': api/macros/json_throw_user.md
- 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE': api/macros/nlohmann_define_type_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md
- 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md
- 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md
- 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md
- 'NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md
# Extras
extra:
@ -289,6 +313,7 @@ plugins:
lang: en
- minify:
minify_html: true
- git-revision-date-localized
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML

View File

@ -1,29 +1,48 @@
click>=7.1.2
future>=0.18.2
htmlmin>=0.1.12
httplib2>=0.18.1
importlib-metadata>=1.6.0
Jinja2>=2.11.2
joblib>=0.15.1
jsmin>=2.2.2
livereload>=2.6.1
lunr>=0.5.8
Markdown>=3.2.2
markdown-include>=0.5.1
MarkupSafe>=1.1.1
mkdocs>=1.1.2
mkdocs-material>=5.2.1
mkdocs-material-extensions>=1.0
mkdocs-minify-plugin>=0.3.0
mkdocs-simple-hooks>=0.1.1
nltk>=3.5
plantuml>=0.3.0
plantuml-markdown>=3.2.2
Pygments>=2.6.1
pymdown-extensions>=7.1
PyYAML>=5.3.1
regex>=2020.5.14
six>=1.15.0
tornado>=6.0.4
tqdm>=4.46.0
zipp>=3.1.0
Babel==2.10.1
certifi==2021.10.8
charset-normalizer==2.0.12
click==8.1.2
csscompressor==0.9.5
future==0.18.2
ghp-import==2.0.2
gitdb==4.0.9
GitPython==3.1.27
htmlmin==0.1.12
httplib2==0.20.4
idna==3.3
importlib-metadata==4.11.3
Jinja2==3.1.1
joblib==1.1.0
jsmin==3.0.1
livereload==2.6.3
lunr==0.6.2
Markdown==3.3.6
markdown-include==0.6.0
MarkupSafe==2.1.1
mergedeep==1.3.4
mkdocs==1.3.0
mkdocs-git-revision-date-localized-plugin==1.0.1
mkdocs-material==8.2.10
mkdocs-material-extensions==1.0.3
mkdocs-minify-plugin==0.5.0
mkdocs-simple-hooks==0.1.5
nltk==3.7
packaging==21.3
plantuml==0.3.0
plantuml-markdown==3.5.2
Pygments==2.11.0
pymdown-extensions==9.3
pyparsing==3.0.8
python-dateutil==2.8.2
pytz==2022.1
PyYAML==6.0
pyyaml_env_tag==0.1
regex==2022.4.24
requests==2.27.1
six==1.16.0
smmap==5.0.0
tornado==6.1
tqdm==4.64.0
urllib3==1.26.9
watchdog==2.1.7
zipp==3.8.0

63
doc/mkdocs/scripts/check_structure.py Normal file → Executable file
View File

@ -2,10 +2,19 @@
import glob
import os.path
import re
warnings = 0
def report(rule, location, description):
global warnings
warnings += 1
print(f'{warnings:3}. {location}: {description} [{rule}]')
def check_structure():
expected_headers = [
expected_sections = [
'Template parameters',
'Specializations',
'Iterator invalidation',
@ -23,13 +32,14 @@ def check_structure():
'Exceptions',
'Complexity',
'Possible implementation',
'Default definition',
'Notes',
'Examples',
'See also',
'Version history'
]
required_headers = [
required_sections = [
'Examples',
'Version history'
]
@ -37,8 +47,8 @@ def check_structure():
files = sorted(glob.glob('api/**/*.md', recursive=True))
for file in files:
with open(file) as file_content:
header_idx = -1
existing_headers = []
section_idx = -1
existing_sections = []
in_initial_code_example = False
previous_line = None
h1sections = 0
@ -51,50 +61,55 @@ def check_structure():
# there should only be one top-level title
if h1sections > 1:
print(f'{file}:{lineno+1}: Error: unexpected top-level title "{line}"!')
report('structure/unexpected_section', f'{file}:{lineno+1}', f'unexpected top-level title "{line}"')
h1sections = 1
# Overview pages should have a better title
if line == '# Overview':
print(f'{file}:{lineno+1}: Error: overview pages should have a better title!')
report('style/title', f'{file}:{lineno+1}', 'overview pages should have a better title than "Overview"')
# lines longer than 160 characters are bad (unless they are tables)
if len(line) > 160 and '|' not in line:
print(f'{file}:{lineno+1}: Error: line is too long ({len(line)} vs. 160 chars)!')
report('whitespace/line_length', f'{file}:{lineno+1}', f'line is too long ({len(line)} vs. 160 chars)')
# check if headers are correct
# check if sections are correct
if line.startswith('## '):
header = line.strip('## ')
existing_headers.append(header)
current_section = line.strip('## ')
existing_sections.append(current_section)
if header in expected_headers:
idx = expected_headers.index(header)
if idx <= header_idx:
print(f'{file}:{lineno+1}: Error: header "{header}" is in an unexpected order (should be before "{expected_headers[header_idx]}")!')
header_idx = idx
if current_section in expected_sections:
idx = expected_sections.index(current_section)
if idx <= section_idx:
report('structure/section_order', f'{file}:{lineno+1}', f'section "{current_section}" is in an unexpected order (should be before "{expected_sections[section_idx]}")')
section_idx = idx
else:
print(f'{file}:{lineno+1}: Error: header "{header}" is not part of the expected headers!')
report('structure/unknown_section', f'{file}:{lineno+1}', f'section "{current_section}" is not part of the expected sections')
# code example
if line == '```cpp' and header_idx == -1:
if line == '```cpp' and section_idx == -1:
in_initial_code_example = True
if in_initial_code_example and line.startswith('//'):
if any(map(str.isdigit, line)) and '(' not in line:
print(f'{file}:{lineno+1}: Number should be in parentheses: {line}')
report('style/numbering', f'{file}:{lineno+1}', 'number should be in parentheses: {line}')
if line == '```' and in_initial_code_example:
in_initial_code_example = False
# consecutive blank lines are bad
if line == '' and previous_line == '':
print(f'{file}:{lineno}-{lineno+1}: Error: Consecutive blank lines!')
report('whitespace/blank_lines', f'{file}:{lineno}-{lineno+1}', 'consecutive blank lines')
# check that non-example admonitions have titles
untitled_admonition = re.match(r'^(\?\?\?|!!!) ([^ ]+)$', line)
if untitled_admonition and untitled_admonition.group(2) != 'example':
report('style/admonition_title', f'{file}:{lineno}', f'"{untitled_admonition.group(2)}" admonitions should have a title')
previous_line = line
for required_header in required_headers:
if required_header not in existing_headers:
print(f'{file}:{lineno+1}: Error: required header "{required_header}" was not found!')
for required_section in required_sections:
if required_section not in existing_sections:
report('structure/missing_section', f'{file}:{lineno+1}', f'required section "{required_section}" was not found')
def check_examples():
@ -113,9 +128,11 @@ def check_examples():
break
if not found:
print(f'{example_file}: Error: example file is not used in any documentation file!')
report('examples/missing', f'{example_file}', 'example file is not used in any documentation file')
if __name__ == '__main__':
print(120 * '-')
check_structure()
check_examples()
print(120 * '-')