mirror of
https://github.com/nlohmann/json.git
synced 2026-10-11 17:07:15 +00:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d13c9e7212 | ||
|
|
522e7465b0 | ||
|
|
74aefc3486 | ||
|
|
84ee12a67c | ||
|
|
2913e96433 | ||
|
|
44e8597701 | ||
|
|
374dfe4f0f | ||
|
|
d540750f21 | ||
|
|
69a0c1b82c | ||
|
|
d33068da73 | ||
|
|
d8dfc0d0f9 | ||
|
|
3d7f554927 | ||
|
|
a269794db7 | ||
|
|
fe4e78e867 | ||
|
|
9196e92520 | ||
|
|
7d22d865dd | ||
|
|
4c73319d3b | ||
|
|
da5097abcd | ||
|
|
2319f6e6f9 | ||
|
|
9a0d1c0c47 | ||
|
|
1bbb5d400a | ||
|
|
08d18d5a82 | ||
|
|
a27065bd12 | ||
|
|
3940f4b730 | ||
|
|
0663907b68 | ||
|
|
f23b3c63a2 |
No files matched your search
@@ -0,0 +1,81 @@
|
||||
name: "Check API documentation"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check_api_docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout pull request
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install clang
|
||||
# Used only as a subprocess for `clang++ -E -v` system-include-path discovery in
|
||||
# extract_api.py; it does not need to version-match the pinned libclang pip wheel
|
||||
# below, which does the actual AST parsing. Do not "fix" this to be version-matched.
|
||||
run: sudo apt-get update && sudo apt-get install -y clang
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: pip install -r tools/api_checker/requirements.txt
|
||||
|
||||
- name: Extract API and regenerate the committed surface file
|
||||
run: |
|
||||
python3 tools/api_checker/extract_api.py \
|
||||
--header include/nlohmann/json.hpp \
|
||||
--include include \
|
||||
--output /tmp/api_snapshot.json \
|
||||
--surface-output tools/api_checker/api_surface.json
|
||||
|
||||
- name: "Check API documentation (Phase 1: advisory)"
|
||||
# Surfaces missing/broken @sa links without failing the job while the backlog from the
|
||||
# initial AST-based rollout is burned down. See tools/api_checker/POLICY.md and the PR
|
||||
# that introduced this workflow for the two-phase rollout plan.
|
||||
continue-on-error: true
|
||||
run: |
|
||||
python3 tools/api_checker/check_docs.py \
|
||||
--snapshot /tmp/api_snapshot.json
|
||||
|
||||
- name: Check macro documentation (advisory only)
|
||||
# Cross-checks docs/mkdocs/docs/api/macros/ pages against #define sites. Only checks the
|
||||
# documented-macro-still-exists direction; never blocks CI. See POLICY.md.
|
||||
run: python3 tools/api_checker/check_macros.py
|
||||
|
||||
- name: Check for uncommitted API surface changes
|
||||
id: diff
|
||||
run: |
|
||||
mkdir -p ${{ github.workspace }}/patch
|
||||
git diff --patch --no-color -- tools/api_checker/api_surface.json > ${{ github.workspace }}/patch/api_surface.patch
|
||||
if [ -s ${{ github.workspace }}/patch/api_surface.patch ]; then
|
||||
echo "tools/api_checker/api_surface.json is out of date. Diff:"
|
||||
cat ${{ github.workspace }}/patch/api_surface.patch
|
||||
echo "has_diff=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "has_diff=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Uploaded so contributors can fix their PR with `git apply api_surface.patch`
|
||||
# instead of installing libclang locally.
|
||||
- name: Upload patch
|
||||
if: steps.diff.outputs.has_diff == 'true'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: api-surface-patch
|
||||
path: patch/api_surface.patch
|
||||
|
||||
- name: Fail if API surface file is not up to date
|
||||
# Unlike the doc-backlog check above, this is purely mechanical regeneration with no
|
||||
# backlog to phase in -- blocking from the start, matching check_amalgamation.yml's
|
||||
# precedent. Contributors who add/remove/rename public API must regenerate and commit
|
||||
# tools/api_checker/api_surface.json as part of their PR.
|
||||
if: steps.diff.outputs.has_diff == 'true'
|
||||
run: exit 1
|
||||
@@ -166,6 +166,13 @@ jobs:
|
||||
# link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash
|
||||
# before doctest prints its first line - 39 of 102 tests on clang 18.
|
||||
# Keep the objects small by splitting the test files instead.
|
||||
# Objects with more than 65535 sections fail to link with "relocation
|
||||
# truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata'": the MinGW
|
||||
# linker stores the section an associative COMDAT section belongs to in
|
||||
# 16 bits (x_associated in binutils' include/coff/internal.h), so it
|
||||
# discards the jump tables of inline functions together with the wrong
|
||||
# function. Each basic_json specialization a test file instantiates adds
|
||||
# many sections, so test a second one in a file of its own.
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build ^
|
||||
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*.gcno
|
||||
*.gcda
|
||||
.DS_Store
|
||||
__pycache__/
|
||||
|
||||
/.idea
|
||||
/cmake-build-*
|
||||
@@ -45,5 +46,9 @@ venv
|
||||
|
||||
nlohmann_json.spdx
|
||||
|
||||
# api_checker: ephemeral, location/doc-status-sensitive working file (not the committed
|
||||
# release-tracking artifact -- see tools/api_checker/api_surface.json for that)
|
||||
/tools/api_checker/api_snapshot.json
|
||||
|
||||
# Bazel-related
|
||||
MODULE.bazel.lock
|
||||
@@ -104,7 +104,7 @@ Thanks everyone!
|
||||
|
||||
:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/docs/mkdocs/docs/examples), or browse through the [**help pages**](https://json.nlohmann.me).
|
||||
|
||||
:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or have a look at the [quick reference](#quick-reference) below.
|
||||
:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or have a look at the [quick reference](#quick-reference) below. The public API surface is derived mechanically and checked for documentation coverage by the tooling in [`tools/api_checker/`](tools/api_checker/), whose [POLICY.md](tools/api_checker/POLICY.md) defines what counts as public API and what stability is guaranteed.
|
||||
|
||||
:bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as much information as possible to help us understand and reproduce your issue.
|
||||
|
||||
|
||||
@@ -9,11 +9,13 @@ INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer::to_json', 'Fu
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype', 'Class', 'api/byte_container_with_subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::byte_container_with_subtype', 'Constructor', 'api/byte_container_with_subtype/byte_container_with_subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::clear_subtype', 'Method', 'api/byte_container_with_subtype/clear_subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::container_type', 'Type', 'api/byte_container_with_subtype/container_type/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::has_subtype', 'Method', 'api/byte_container_with_subtype/has_subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::operator!=', 'Operator', 'api/byte_container_with_subtype/operator_ne/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::operator==', 'Operator', 'api/byte_container_with_subtype/operator_eq/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::set_subtype', 'Method', 'api/byte_container_with_subtype/set_subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::subtype', 'Method', 'api/byte_container_with_subtype/subtype/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::subtype_type', 'Type', 'api/byte_container_with_subtype/subtype_type/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/basic_json/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('format_as', 'Function', 'api/basic_json/format_as/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::accept', 'Function', 'api/basic_json/accept/index.html');
|
||||
@@ -26,6 +28,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::basic_json', 'Con
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::begin', 'Method', 'api/basic_json/begin/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary', 'Function', 'api/basic_json/binary/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary_t', 'Type', 'api/basic_json/binary_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::bjdata_version_t', 'Enum', 'api/basic_json/bjdata_version_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::boolean_t', 'Type', 'api/basic_json/boolean_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbegin', 'Method', 'api/basic_json/cbegin/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbor_tag_handler_t', 'Enum', 'api/basic_json/cbor_tag_handler_t/index.html');
|
||||
@@ -61,6 +64,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_binary', 'Met
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ptr', 'Method', 'api/basic_json/get_ptr/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ref', 'Method', 'api/basic_json/get_ref/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_to', 'Method', 'api/basic_json/get_to/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::initializer_list_t', 'Type', 'api/basic_json/initializer_list_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::input_format_t', 'Enum', 'api/basic_json/input_format_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::insert', 'Method', 'api/basic_json/insert/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::invalid_iterator', 'Class', 'api/basic_json/invalid_iterator/index.html');
|
||||
@@ -79,6 +83,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_string', 'Meth
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_structured', 'Method', 'api/basic_json/is_structured/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::items', 'Method', 'api/basic_json/items/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_base_class_t', 'Type', 'api/basic_json/json_base_class_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_sax_t', 'Type', 'api/basic_json/json_sax_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_serializer', 'Class', 'api/basic_json/json_serializer/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::max_size', 'Method', 'api/basic_json/max_size/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::merge_patch', 'Method', 'api/basic_json/merge_patch/index.html');
|
||||
@@ -154,24 +159,44 @@ INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::string_t', 'Typ
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::to_string', 'Method', 'api/json_pointer/to_string/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax', 'Class', 'api/json_sax/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::binary', 'Method', 'api/json_sax/binary/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::binary_t', 'Type', 'api/json_sax/binary_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::boolean', 'Method', 'api/json_sax/boolean/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_array', 'Method', 'api/json_sax/end_array/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_object', 'Method', 'api/json_sax/end_object/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::json_sax', 'Constructor', 'api/json_sax/json_sax/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::key', 'Method', 'api/json_sax/key/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::null', 'Method', 'api/json_sax/null/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_float', 'Method', 'api/json_sax/number_float/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_float_t', 'Type', 'api/json_sax/number_float_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_integer', 'Method', 'api/json_sax/number_integer/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_integer_t', 'Type', 'api/json_sax/number_integer_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_unsigned', 'Method', 'api/json_sax/number_unsigned/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_unsigned_t', 'Type', 'api/json_sax/number_unsigned_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::operator=', 'Operator', 'api/json_sax/operator=/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::parse_error', 'Method', 'api/json_sax/parse_error/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_array', 'Method', 'api/json_sax/start_array/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_object', 'Method', 'api/json_sax/start_object/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::string', 'Method', 'api/json_sax/string/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::string_t', 'Type', 'api/json_sax/string_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::~json_sax', 'Method', 'api/json_sax/~json_sax/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json', 'Literal', 'api/operator_literal_json/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json_pointer', 'Literal', 'api/operator_literal_json_pointer/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('operator<<', 'Operator', 'api/operator_ltlt/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('operator>>', 'Operator', 'api/operator_gtgt/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_json', 'Class', 'api/ordered_json/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map', 'Class', 'api/ordered_map/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::Container', 'Type', 'api/ordered_map/Container/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::at', 'Method', 'api/ordered_map/at/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::count', 'Method', 'api/ordered_map/count/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::emplace', 'Method', 'api/ordered_map/emplace/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::erase', 'Method', 'api/ordered_map/erase/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::find', 'Method', 'api/ordered_map/find/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::insert', 'Method', 'api/ordered_map/insert/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::key_compare', 'Type', 'api/ordered_map/key_compare/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::operator=', 'Operator', 'api/ordered_map/operator=/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::operator[]', 'Operator', 'api/ordered_map/operator[]/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::ordered_map', 'Constructor', 'api/ordered_map/ordered_map/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map::~ordered_map', 'Method', 'api/ordered_map/~ordered_map/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('std::formatter<basic_json>', 'Class', 'api/basic_json/std_formatter/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('std::hash<basic_json>', 'Class', 'api/basic_json/std_hash/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('std::swap<basic_json>', 'Function', 'api/basic_json/std_swap/index.html');
|
||||
|
||||
@@ -475,8 +475,10 @@ basic_json(basic_json&& other) noexcept;
|
||||
1. Since version 1.0.0.
|
||||
2. Since version 1.0.0.
|
||||
3. Since version 2.1.0.
|
||||
4. Since version 3.2.0. Explicit for different string types if `JSON_USE_IMPLICIT_CONVERSIONS` is `0` since
|
||||
version 3.13.0.
|
||||
4. Since version 3.2.0. Also initializes the position reported by
|
||||
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) from `val` when
|
||||
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is enabled, since version 3.12.0. Explicit
|
||||
for different string types if `JSON_USE_IMPLICIT_CONVERSIONS` is `0` since version 3.13.0.
|
||||
5. Since version 1.0.0.
|
||||
6. Since version 1.0.0.
|
||||
7. Since version 1.0.0. Fixed in version 3.13.0 to also check the iterator range for binary values; before, a range
|
||||
|
||||
@@ -64,18 +64,7 @@ values of that type directly to a `basic_json` instance, and they will automatic
|
||||
rather than arrays:
|
||||
|
||||
```cpp
|
||||
using custom_json = nlohmann::basic_json<
|
||||
nlohmann::ordered_map, // ObjectType
|
||||
std::vector, // ArrayType
|
||||
std::string, // StringType
|
||||
bool, // BooleanType
|
||||
std::int64_t, // NumberIntegerType
|
||||
std::uint64_t, // NumberUnsignedType
|
||||
double, // NumberFloatType
|
||||
std::allocator, // AllocatorType
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::byte> // Custom BinaryType
|
||||
>;
|
||||
using custom_json = nlohmann::ordered_json::with_binary_t<std::vector<std::byte>>;
|
||||
|
||||
std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}};
|
||||
custom_json j = data; // Creates a binary value, not an array
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# <small>nlohmann::basic_json::</small>bjdata_version_t
|
||||
|
||||
```cpp
|
||||
enum class bjdata_version_t
|
||||
{
|
||||
draft2,
|
||||
draft3,
|
||||
};
|
||||
```
|
||||
|
||||
This enumeration is used in the [`to_bjdata`](to_bjdata.md) function to choose which draft version of
|
||||
the BJData specification to encode ND-array extensions for:
|
||||
|
||||
draft2
|
||||
: encode using the BJData Draft 2 ND-array format
|
||||
|
||||
draft3
|
||||
: encode using the BJData Draft 3 ND-array format
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `bjdata_version_t` selects the BJData draft used by `to_bjdata`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/bjdata_version_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/bjdata_version_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.0.
|
||||
@@ -0,0 +1,32 @@
|
||||
# <small>nlohmann::basic_json::</small>initializer_list_t
|
||||
|
||||
```cpp
|
||||
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||
```
|
||||
|
||||
The type used for the initializer-list [constructor](basic_json.md) (overload 5) and for functions
|
||||
such as [`operator=`](operator=.md) that accept a braced-init-list of JSON values. Each element wraps a
|
||||
`basic_json` value or something convertible to one, deferring the decision of whether the list should be
|
||||
parsed as a JSON array or a JSON object to the constructor itself.
|
||||
|
||||
See the [constructor](basic_json.md) documentation for how `initializer_list_t` values are interpreted.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how an `initializer_list_t` is used to construct a JSON value.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/initializer_list_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/initializer_list_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Since version 1.0.0.
|
||||
@@ -0,0 +1,31 @@
|
||||
# <small>nlohmann::basic_json::</small>json_sax_t
|
||||
|
||||
```cpp
|
||||
using json_sax_t = json_sax<basic_json>;
|
||||
```
|
||||
|
||||
The [`json_sax`](../json_sax/index.md) interface bound to this `basic_json` specialization, i.e. with
|
||||
`BasicJsonType` fixed to `basic_json`. Used as the SAX interface type by [`sax_parse`](sax_parse.md) and
|
||||
other SAX-based parsing functions.
|
||||
|
||||
See [`nlohmann::json_sax`](../json_sax/index.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `json_sax_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -26,7 +26,8 @@ To store objects in C++, a type is defined by the template parameters described
|
||||
|
||||
`StringType`
|
||||
: the type of the keys or names (e.g., `std::string`). The comparison function `std::less<StringType>` is used to
|
||||
order elements inside the container.
|
||||
order elements inside the container. `object_t::key_type` must be implicitly convertible to `string_t` (required by the
|
||||
binary formats).
|
||||
|
||||
`AllocatorType`
|
||||
: the allocator to use for objects (e.g., `std::allocator`)
|
||||
|
||||
@@ -51,3 +51,5 @@ Linear.
|
||||
## Version history
|
||||
|
||||
- Added in version 1.0.0.
|
||||
- The `noexcept` specification was extended to also depend on
|
||||
[`json_base_class_t`](json_base_class_t.md)'s move-assignment in version 3.11.3.
|
||||
@@ -92,3 +92,8 @@ Linear in the size of the JSON value.
|
||||
- Since version 1.0.0.
|
||||
- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) added
|
||||
in version 3.9.0.
|
||||
- The exclusion of `std::any` from this conversion became conditional on
|
||||
[`JSON_HAS_STATIC_RTTI`](../macros/json_has_static_rtti.md) in version 3.11.3.
|
||||
- `std::optional<T>` excluded from this conversion in version 3.13.0; use
|
||||
[`get<std::optional<T>>()`](get.md)/[`get_to()`](get_to.md) instead (see
|
||||
[Converting values](../../features/conversions.md)).
|
||||
@@ -0,0 +1,32 @@
|
||||
# <small>nlohmann::byte_container_with_subtype::</small>container_type
|
||||
|
||||
```cpp
|
||||
using container_type = BinaryType;
|
||||
```
|
||||
|
||||
The type of the underlying binary container, forwarded from the `BinaryType` template parameter that
|
||||
`byte_container_with_subtype` is instantiated with. `byte_container_with_subtype` publicly inherits from
|
||||
`container_type`.
|
||||
|
||||
See [`basic_json::binary_t`](../basic_json/binary_t.md) for the type typically used to instantiate
|
||||
`BinaryType`.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `container_type`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/byte_container_with_subtype__container_type.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/byte_container_with_subtype__container_type.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Since version 3.8.0.
|
||||
@@ -0,0 +1,28 @@
|
||||
# <small>nlohmann::byte_container_with_subtype::</small>subtype_type
|
||||
|
||||
```cpp
|
||||
using subtype_type = std::uint64_t;
|
||||
```
|
||||
|
||||
The type used to store the optional binary subtype tag. See [`subtype`](subtype.md) and
|
||||
[`set_subtype`](set_subtype.md).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `subtype_type`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/byte_container_with_subtype__subtype_type.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/byte_container_with_subtype__subtype_type.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Since version 3.8.0.
|
||||
@@ -0,0 +1,30 @@
|
||||
# <small>nlohmann::json_sax::</small>binary_t
|
||||
|
||||
```cpp
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
```
|
||||
|
||||
The type used by the [`binary`](binary.md) callback for JSON binary values, forwarded from the
|
||||
`BasicJsonType` template parameter.
|
||||
|
||||
See [`basic_json::binary_t`](../basic_json/binary_t.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `binary_t` and its relation to `basic_json::binary_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax__binary_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax__binary_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.8.0.
|
||||
@@ -0,0 +1,33 @@
|
||||
# <small>nlohmann::json_sax::</small>json_sax
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
json_sax() = default;
|
||||
|
||||
// (2)
|
||||
json_sax(const json_sax&) = default;
|
||||
|
||||
// (3)
|
||||
json_sax(json_sax&&) noexcept = default;
|
||||
```
|
||||
|
||||
1. Default constructor.
|
||||
2. Copy constructor.
|
||||
3. Move constructor.
|
||||
|
||||
`json_sax` is a pure abstract base class with no data members of its own, so all three constructors are
|
||||
defaulted and only exist to make derived SAX consumers explicitly copyable/movable.
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: none of these constructors throw exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,30 @@
|
||||
# <small>nlohmann::json_sax::</small>number_float_t
|
||||
|
||||
```cpp
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
```
|
||||
|
||||
The type used by the [`number_float`](number_float.md) callback for JSON floating-point numbers,
|
||||
forwarded from the `BasicJsonType` template parameter.
|
||||
|
||||
See [`basic_json::number_float_t`](../basic_json/number_float_t.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `number_float_t` and its relation to `basic_json::number_float_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax__number_float_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax__number_float_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,30 @@
|
||||
# <small>nlohmann::json_sax::</small>number_integer_t
|
||||
|
||||
```cpp
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
```
|
||||
|
||||
The type used by the [`number_integer`](number_integer.md) callback for JSON integer numbers, forwarded
|
||||
from the `BasicJsonType` template parameter.
|
||||
|
||||
See [`basic_json::number_integer_t`](../basic_json/number_integer_t.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `number_integer_t` and its relation to `basic_json::number_integer_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax__number_integer_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax__number_integer_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,30 @@
|
||||
# <small>nlohmann::json_sax::</small>number_unsigned_t
|
||||
|
||||
```cpp
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
```
|
||||
|
||||
The type used by the [`number_unsigned`](number_unsigned.md) callback for JSON unsigned integer numbers,
|
||||
forwarded from the `BasicJsonType` template parameter.
|
||||
|
||||
See [`basic_json::number_unsigned_t`](../basic_json/number_unsigned_t.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `number_unsigned_t` and its relation to `basic_json::number_unsigned_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax__number_unsigned_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax__number_unsigned_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,29 @@
|
||||
# <small>nlohmann::json_sax::</small>operator=
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
json_sax& operator=(const json_sax&) = default;
|
||||
|
||||
// (2)
|
||||
json_sax& operator=(json_sax&&) noexcept = default;
|
||||
```
|
||||
|
||||
1. Copy assignment operator.
|
||||
2. Move assignment operator.
|
||||
|
||||
`json_sax` is a pure abstract base class with no data members of its own, so both assignment operators
|
||||
are defaulted and only exist to make derived SAX consumers explicitly copy-/move-assignable.
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: neither operator throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,30 @@
|
||||
# <small>nlohmann::json_sax::</small>string_t
|
||||
|
||||
```cpp
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
```
|
||||
|
||||
The type used by the [`string`](string.md) and [`key`](key.md) callbacks for JSON strings and object
|
||||
keys, forwarded from the `BasicJsonType` template parameter.
|
||||
|
||||
See [`basic_json::string_t`](../basic_json/string_t.md) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `string_t` and its relation to `basic_json::string_t`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_sax__string_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_sax__string_t.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -0,0 +1,22 @@
|
||||
# <small>nlohmann::json_sax::</small>~json_sax
|
||||
|
||||
```cpp
|
||||
virtual ~json_sax() = default;
|
||||
```
|
||||
|
||||
Destructor. Virtual to allow proper destruction of derived SAX consumer classes through a
|
||||
pointer/reference to `json_sax`.
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this destructor never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.2.0.
|
||||
@@ -67,7 +67,7 @@ By default, implicit conversions are enabled.
|
||||
`JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`:
|
||||
|
||||
```cpp
|
||||
using wjson = nlohmann::basic_json<std::map, std::vector, std::wstring>;
|
||||
using wjson = nlohmann::json::with_string_t<std::wstring>;
|
||||
|
||||
void load(const nlohmann::json& j);
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@ This type preserves the insertion order of object keys.
|
||||
|
||||
## Iterator invalidation
|
||||
|
||||
The type is based on [`ordered_map`](ordered_map.md) which in turn uses a `std::vector` to store object elements.
|
||||
The type is based on [`ordered_map`](ordered_map/index.md) which in turn uses a `std::vector` to store object elements.
|
||||
Therefore, adding object elements can yield a reallocation in which case all iterators (including the
|
||||
[`end()`](basic_json/end.md) iterator) and all references to the elements are invalidated. Also, any iterator or
|
||||
reference after the insertion point will point to the same index, which is now a different value.
|
||||
|
||||
## Complexity
|
||||
|
||||
[`ordered_map`](ordered_map.md) has no lookup index: every key-based object operation is a linear scan, so building or
|
||||
[`ordered_map`](ordered_map/index.md) has no lookup index: every key-based object operation is a linear scan, so building or
|
||||
parsing an object of `n` keys costs O(n²) rather than O(n log n). See
|
||||
[`ordered_map` complexity](ordered_map.md#complexity) for the per-operation table and for measured numbers.
|
||||
[`ordered_map` complexity](ordered_map/index.md#complexity) for the per-operation table and for measured numbers.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -37,7 +37,7 @@ parsing an object of `n` keys costs O(n²) rather than O(n log n). See
|
||||
|
||||
## See also
|
||||
|
||||
- [ordered_map](ordered_map.md)
|
||||
- [ordered_map](ordered_map/index.md)
|
||||
- [Object Order](../features/object_order.md)
|
||||
|
||||
## Version history
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# <small>nlohmann::ordered_map::</small>Container
|
||||
|
||||
```cpp
|
||||
using Container = std::vector<std::pair<const Key, T>, Allocator>;
|
||||
```
|
||||
|
||||
The base container type that `ordered_map` publicly inherits from. Elements are stored in insertion
|
||||
order as `#!cpp std::pair<const Key, T>` entries in a `std::vector`.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows the type `Container`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__Container.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__Container.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
@@ -0,0 +1,61 @@
|
||||
# <small>nlohmann::ordered_map::</small>at
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
T& at(const key_type& key);
|
||||
const T& at(const key_type& key) const;
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
T& at(KeyType&& key);
|
||||
template<class KeyType>
|
||||
const T& at(KeyType&& key) const;
|
||||
```
|
||||
|
||||
1. Returns a reference to the value mapped to `key`.
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup, e.g. looking up by a `#!cpp const char*` without constructing a temporary
|
||||
`key_type`). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the element to find
|
||||
|
||||
## Return value
|
||||
|
||||
reference to the mapped value of the element with key equal to `key`
|
||||
|
||||
## Exceptions
|
||||
|
||||
Throws `std::out_of_range` if no element with key `key` exists.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `at` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__at.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__at.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.1 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -0,0 +1,53 @@
|
||||
# <small>nlohmann::ordered_map::</small>count
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
size_type count(const key_type& key) const;
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
size_type count(KeyType&& key) const;
|
||||
```
|
||||
|
||||
1. Returns the number of elements with key equal to `key` (0 or 1, since keys are unique).
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the elements to count
|
||||
|
||||
## Return value
|
||||
|
||||
number of elements with key equal to `key` (0 or 1)
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `count` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__count.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__count.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.1 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -0,0 +1,58 @@
|
||||
# <small>nlohmann::ordered_map::</small>emplace
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
std::pair<iterator, bool> emplace(const key_type& key, T&& t);
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
std::pair<iterator, bool> emplace(KeyType&& key, T&& t);
|
||||
```
|
||||
|
||||
1. Inserts `#!cpp {key, t}` if no element with an equal key already exists (per [`key_compare`](key_compare.md)),
|
||||
appending it at the end to preserve insertion order. If an equal key already exists, does nothing.
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the element to insert
|
||||
|
||||
`t` (in)
|
||||
: value of the element to insert
|
||||
|
||||
## Return value
|
||||
|
||||
pair of an iterator to the (possibly newly inserted) element, and a `bool` that is `true` if insertion
|
||||
took place and `false` if an element with an equal key already existed
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `emplace` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__emplace.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__emplace.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -0,0 +1,75 @@
|
||||
# <small>nlohmann::ordered_map::</small>erase
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
size_type erase(const key_type& key);
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
size_type erase(KeyType&& key);
|
||||
|
||||
// (3)
|
||||
iterator erase(iterator pos);
|
||||
|
||||
// (4)
|
||||
iterator erase(iterator first, iterator last);
|
||||
```
|
||||
|
||||
1. Removes the element with key equal to `key`, if any, preserving the relative order of the remaining
|
||||
elements.
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
3. Removes the element at `pos`.
|
||||
4. Removes the elements in range `[first, last)`.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the element to remove
|
||||
|
||||
`pos` (in)
|
||||
: iterator to the element to remove
|
||||
|
||||
`first` (in)
|
||||
: iterator to the first element to remove
|
||||
|
||||
`last` (in)
|
||||
: iterator one past the last element to remove
|
||||
|
||||
## Return value
|
||||
|
||||
1. number of elements removed (0 or 1)
|
||||
2. number of elements removed (0 or 1)
|
||||
3. iterator following the removed element
|
||||
4. iterator following the last removed element
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements (elements after the removed one(s) are shifted to keep storage
|
||||
contiguous).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `erase` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__erase.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__erase.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -0,0 +1,56 @@
|
||||
# <small>nlohmann::ordered_map::</small>find
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
iterator find(const key_type& key);
|
||||
const_iterator find(const key_type& key) const;
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
iterator find(KeyType&& key);
|
||||
template<class KeyType>
|
||||
const_iterator find(KeyType&& key) const;
|
||||
```
|
||||
|
||||
1. Returns an iterator to the element with key equal to `key`, or `end()` if no such element exists.
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the element to find
|
||||
|
||||
## Return value
|
||||
|
||||
iterator to the element with key equal to `key`, or `end()` if not found
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `find` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__find.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__find.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.1 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -6,7 +6,7 @@ template<class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>;
|
||||
```
|
||||
|
||||
A minimal map-like container that preserves insertion order for use within [`nlohmann::ordered_json`](ordered_json.md)
|
||||
A minimal map-like container that preserves insertion order for use within [`nlohmann::ordered_json`](../ordered_json.md)
|
||||
(`nlohmann::basic_json<ordered_map>`).
|
||||
|
||||
## Template parameters
|
||||
@@ -30,19 +30,19 @@ case all iterators (including the `end()` iterator) and all references to the el
|
||||
|
||||
When the storage grows, the keys are copied and the mapped values are moved to the new storage. A plain `std::vector`
|
||||
would copy the whole elements instead, because their `#!cpp const` keys make them not nothrow move constructible; for
|
||||
[`ordered_json`](ordered_json.md), this would be a deep copy of every nested value. The values are only copied if
|
||||
[`ordered_json`](../ordered_json.md), this would be a deep copy of every nested value. The values are only copied if
|
||||
`T` is not default constructible or not nothrow move assignable.
|
||||
|
||||
## Member types
|
||||
|
||||
- **key_type** - key type (`Key`)
|
||||
- **mapped_type** - mapped type (`T`)
|
||||
- **Container** - base container type (`#!cpp std::vector<std::pair<const Key, T>, Allocator>`)
|
||||
- [**Container**](Container.md) - base container type (`#!cpp std::vector<std::pair<const Key, T>, Allocator>`)
|
||||
- **iterator**
|
||||
- **const_iterator**
|
||||
- **size_type**
|
||||
- **value_type**
|
||||
- **key_compare** - key comparison function
|
||||
- [**key_compare**](key_compare.md) - key comparison function
|
||||
```cpp
|
||||
std::equal_to<Key> // until C++14
|
||||
|
||||
@@ -51,15 +51,16 @@ std::equal_to<> // since C++14
|
||||
|
||||
## Member functions
|
||||
|
||||
- (constructor)
|
||||
- (destructor)
|
||||
- **emplace**
|
||||
- **operator\[\]**
|
||||
- **at**
|
||||
- **erase**
|
||||
- **count**
|
||||
- **find**
|
||||
- **insert**
|
||||
- [(constructor)](ordered_map.md)
|
||||
- [(destructor)](~ordered_map.md)
|
||||
- [**operator=**](operator=.md)
|
||||
- [**emplace**](emplace.md)
|
||||
- [**operator\[\]**](operator[].md)
|
||||
- [**at**](at.md)
|
||||
- [**erase**](erase.md)
|
||||
- [**count**](count.md)
|
||||
- [**find**](find.md)
|
||||
- [**insert**](insert.md)
|
||||
|
||||
## Exception safety
|
||||
|
||||
@@ -89,7 +90,7 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
|
||||
!!! warning "Quadratic cost of building large objects"
|
||||
|
||||
Because every insertion scans all elements inserted so far, building an object of `n` distinct keys costs
|
||||
**O(n²)** in total. This applies to filling an [`ordered_json`](ordered_json.md) object key by key as well as to
|
||||
**O(n²)** in total. This applies to filling an [`ordered_json`](../ordered_json.md) object key by key as well as to
|
||||
parsing one, since the parser inserts each key as it is read.
|
||||
|
||||
The cost is negligible for the object sizes typically found in configuration files or API payloads, but it grows
|
||||
@@ -106,7 +107,7 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
|
||||
If key order matters for objects of that size, consider a container with a lookup index, such as
|
||||
[`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map)
|
||||
([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)), as the object type -- see
|
||||
[object order](../features/object_order.md).
|
||||
[object order](../../features/object_order.md).
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -126,10 +127,10 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
|
||||
|
||||
## See also
|
||||
|
||||
- [ordered_json](ordered_json.md)
|
||||
- [ordered_json](../ordered_json.md)
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Added **key_compare** member in version 3.11.0.
|
||||
- Changed in version 3.13.0: growing the storage moves the mapped values instead of copying them.
|
||||
@@ -0,0 +1,63 @@
|
||||
# <small>nlohmann::ordered_map::</small>insert
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
std::pair<iterator, bool> insert(value_type&& value);
|
||||
std::pair<iterator, bool> insert(const value_type& value);
|
||||
|
||||
// (2)
|
||||
template<typename InputIt>
|
||||
void insert(InputIt first, InputIt last);
|
||||
```
|
||||
|
||||
1. Inserts `value` if no element with an equal key already exists (per [`key_compare`](key_compare.md)),
|
||||
appending it at the end to preserve insertion order. If an equal key already exists, does nothing.
|
||||
2. Inserts the elements from range `[first, last)`, in iteration order, applying the same equal-key rule
|
||||
as (1) to each element.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`InputIt`
|
||||
: an input iterator type
|
||||
|
||||
## Parameters
|
||||
|
||||
`value` (in)
|
||||
: value to insert
|
||||
|
||||
`first` (in)
|
||||
: iterator to the first element to insert
|
||||
|
||||
`last` (in)
|
||||
: iterator one past the last element to insert
|
||||
|
||||
## Return value
|
||||
|
||||
1. pair of an iterator to the (possibly newly inserted) element, and a `bool` that is `true` if insertion
|
||||
took place and `false` if an element with an equal key already existed
|
||||
2. (none)
|
||||
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of elements.
|
||||
2. Linear in the distance between `first` and `last`, times linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `insert` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__insert.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__insert.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.1 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
@@ -0,0 +1,34 @@
|
||||
# <small>nlohmann::ordered_map::</small>key_compare
|
||||
|
||||
```cpp
|
||||
using key_compare = std::equal_to<Key>; // until C++14
|
||||
|
||||
using key_compare = std::equal_to<>; // since C++14
|
||||
```
|
||||
|
||||
The comparator used to determine key equality when looking up elements. Unlike `std::map`, `ordered_map`
|
||||
uses linear search with `key_compare` rather than an ordering relation, since element order reflects
|
||||
insertion order rather than key order.
|
||||
|
||||
Since C++14, the transparent `#!cpp std::equal_to<>` is used, which enables heterogeneous lookup (e.g.
|
||||
looking up by a `#!cpp const char*` key without constructing a temporary `Key`).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `key_compare` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__key_compare.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__key_compare.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.11.0.
|
||||
@@ -0,0 +1,32 @@
|
||||
# <small>nlohmann::ordered_map::</small>operator=
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
ordered_map& operator=(const ordered_map& other);
|
||||
|
||||
// (2)
|
||||
ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable<Container>::value);
|
||||
```
|
||||
|
||||
1. Copy assignment operator.
|
||||
2. Move assignment operator.
|
||||
|
||||
## Parameters
|
||||
|
||||
`other` (in)
|
||||
: value to assign from
|
||||
|
||||
## Return value
|
||||
|
||||
`*this`
|
||||
|
||||
## Complexity
|
||||
|
||||
1. Linear in the size of `other`.
|
||||
2. Constant.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
@@ -0,0 +1,62 @@
|
||||
# <small>nlohmann::ordered_map::</small>operator[]
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
T& operator[](const key_type& key);
|
||||
const T& operator[](const key_type& key) const;
|
||||
|
||||
// (2)
|
||||
template<class KeyType>
|
||||
T& operator[](KeyType&& key);
|
||||
template<class KeyType>
|
||||
const T& operator[](KeyType&& key) const;
|
||||
```
|
||||
|
||||
1. Returns a reference to the value mapped to `key`, inserting a default-constructed `T` (non-`const`
|
||||
overload only) if no such element exists yet.
|
||||
2. Same as (1), but for any `KeyType` comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
(heterogeneous lookup). Only participates in overload resolution if `KeyType` is usable as a key type.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`KeyType`
|
||||
: a type comparable to `key_type` via [`key_compare`](key_compare.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
`key` (in)
|
||||
: key of the element to find or insert
|
||||
|
||||
## Return value
|
||||
|
||||
reference to the mapped value of the element with key equal to `key`
|
||||
|
||||
## Exceptions
|
||||
|
||||
The `const` overloads throw `std::out_of_range` if no element with key `key` exists (they delegate to
|
||||
[`at`](at.md)).
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how `operator[]` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_map__operator_idx.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/ordered_map__operator_idx.output"
|
||||
```
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
- Overload (2) added in version 3.11.0.
|
||||
@@ -0,0 +1,66 @@
|
||||
# <small>nlohmann::ordered_map::</small>ordered_map
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
ordered_map() noexcept(noexcept(Container()));
|
||||
|
||||
// (2)
|
||||
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc)));
|
||||
|
||||
// (3)
|
||||
template <class It>
|
||||
ordered_map(It first, It last, const Allocator& alloc = Allocator());
|
||||
|
||||
// (4)
|
||||
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator());
|
||||
|
||||
// (5)
|
||||
ordered_map(const ordered_map&) = default;
|
||||
|
||||
// (6)
|
||||
ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible<Container>::value) = default;
|
||||
```
|
||||
|
||||
1. Default constructor. Creates an empty `ordered_map`.
|
||||
2. Creates an empty `ordered_map` using the given allocator.
|
||||
3. Creates an `ordered_map` from the elements in range `[first, last)`, inserted in iteration order.
|
||||
4. Creates an `ordered_map` from an initializer list of key/value pairs, inserted in list order.
|
||||
5. Copy constructor.
|
||||
6. Move constructor.
|
||||
|
||||
These constructors are declared explicitly (rather than inherited via `#!cpp using Container::Container`)
|
||||
because older compilers (GCC <= 5.5, Xcode <= 9.4) do not handle the inherited constructors correctly.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`It`
|
||||
: an input iterator type
|
||||
|
||||
## Parameters
|
||||
|
||||
`alloc` (in)
|
||||
: allocator to use for the underlying container
|
||||
|
||||
`first` (in)
|
||||
: iterator to the first element to insert
|
||||
|
||||
`last` (in)
|
||||
: iterator one past the last element to insert
|
||||
|
||||
`init` (in)
|
||||
: initializer list of key/value pairs to insert
|
||||
|
||||
## Complexity
|
||||
|
||||
1. Constant.
|
||||
2. Constant.
|
||||
3. Linear in the distance between `first` and `last`.
|
||||
4. Linear in the size of `init`.
|
||||
5. Linear in the size of `other`.
|
||||
6. Constant.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
@@ -0,0 +1,17 @@
|
||||
# <small>nlohmann::ordered_map::</small>~ordered_map
|
||||
|
||||
```cpp
|
||||
~ordered_map() = default;
|
||||
```
|
||||
|
||||
Destroys the `ordered_map` and frees all allocated memory.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements.
|
||||
|
||||
<!-- NOLINT Examples -->
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](../ordered_json.md).
|
||||
@@ -36,13 +36,26 @@ work items are tracked in the [GitHub milestones](https://github.com/nlohmann/js
|
||||
## API stability
|
||||
|
||||
Releases follow [semantic versioning](https://semver.org): a minor or patch release of version 3.x does not break code
|
||||
that uses the public API. In particular, a 3.x release does not:
|
||||
that uses the public API, unless that code opts in to a change with a macro as described [below](#version-40). In
|
||||
particular, a 3.x release does not:
|
||||
|
||||
- change the signature of a function (its parameter types, return type, number of parameters, or the const-ness of a
|
||||
member function);
|
||||
- remove or rename a function or class;
|
||||
- make breaking changes to the signature of a function: the types or order of its existing parameters, its return type,
|
||||
its `noexcept` or `constexpr` specifier, or the const-ness of a member function. New parameters may be added if they
|
||||
have a default value;
|
||||
- remove or rename a function or class, or change the template parameters of a public class template;
|
||||
- change which exceptions a function throws, or the [exception ids](../home/exceptions.md);
|
||||
- change access specifiers or default arguments.
|
||||
- change access specifiers, or change or remove existing default arguments. New default arguments may be added;
|
||||
- change the JSON type that a valid input parses to, or the text that `dump()` produces for a valid value;
|
||||
- accept input that was rejected before, or reject input that was accepted before;
|
||||
- change the order in which the keys of an object are iterated. The default type sorts keys, and
|
||||
[`ordered_json`](../api/ordered_json.md) keeps insertion order;
|
||||
- change when iterators, pointers, or references are invalidated, or the state of a moved-from `basic_json`;
|
||||
- add or remove implicit conversions from `basic_json`;
|
||||
- change how `to_json` and `from_json` functions are found, or the behavior of
|
||||
[`adl_serializer`](../api/adl_serializer/index.md);
|
||||
- add pure virtual functions to the [`json_sax`](../api/json_sax/index.md) interface;
|
||||
- remove, rename, renumber, or add enumerators of `value_t`;
|
||||
- remove or rename a documented macro, CMake option, CMake target, or header, or change what a documented macro does.
|
||||
|
||||
Exceptions to these rules, for instance when fixing a bug requires changing the exception a function throws, are
|
||||
documented in the [release notes](../home/releases.md).
|
||||
@@ -51,13 +64,14 @@ The following are **not** part of the public API and may change in any release,
|
||||
|
||||
- The text of exception messages returned by `what()`. Use the [exception id](../home/exceptions.md) to tell errors
|
||||
apart.
|
||||
- The ABI, including `sizeof(basic_json)` and the memory layout of its values. Recompile your code when you upgrade the
|
||||
library. The [versioned inline namespace](../features/namespace.md) turns mixing versions into a link error.
|
||||
- The ABI, including `sizeof(basic_json)` and the memory layout of its values. The
|
||||
[versioned inline namespace](../features/namespace.md) turns mixing versions into a link error.
|
||||
- The hash values returned by `std::hash` for `basic_json`. Numbers that compare equal still hash equally.
|
||||
- Everything in namespace `nlohmann::detail`, and macros and type traits that are not documented in the
|
||||
[API reference](../api/basic_json/index.md).
|
||||
|
||||
Changes that would break the public API are only added behind a macro whose default keeps the 3.x behavior, see
|
||||
[Version 4.0](#version-40).
|
||||
Breaking changes are only added behind a macro whose default keeps the 3.x behavior. See [Version 4.0](#version-40) and
|
||||
the [macro overview](../features/macros.md).
|
||||
|
||||
## Version 4.0
|
||||
|
||||
|
||||
@@ -15,19 +15,7 @@ class base_class_with_hidden_members
|
||||
}
|
||||
};
|
||||
|
||||
using json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
base_class_with_hidden_members
|
||||
>;
|
||||
using json = nlohmann::json::with_base_class_t<base_class_with_hidden_members>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// an empty binary value is encoded differently by the two drafts:
|
||||
// draft2 omits the optimized type marker for an empty byte array,
|
||||
// while draft3 always writes it
|
||||
json j = json::binary({});
|
||||
|
||||
// encode using BJData draft2 (the default)
|
||||
auto v_draft2 = json::to_bjdata(j, true, true, json::bjdata_version_t::draft2);
|
||||
|
||||
// encode using BJData draft3
|
||||
auto v_draft3 = json::to_bjdata(j, true, true, json::bjdata_version_t::draft3);
|
||||
|
||||
std::cout << "draft2 size: " << v_draft2.size() << '\n'
|
||||
<< "draft3 size: " << v_draft3.size() << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
draft2 size: 4
|
||||
draft3 size: 6
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using byte_container_with_subtype = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<byte_container_with_subtype::container_type, std::vector<std::uint8_t>>::value
|
||||
<< std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using byte_container_with_subtype = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<byte_container_with_subtype::subtype_type, std::uint64_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -19,25 +19,9 @@ int main()
|
||||
<< j.contains("/array/1"_json_pointer) << '\n'
|
||||
<< j.contains("/array/-"_json_pointer) << '\n'
|
||||
<< j.contains("/array/4"_json_pointer) << '\n'
|
||||
<< j.contains("/baz"_json_pointer) << std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
// try to use an array index with leading '0'
|
||||
j.contains("/array/01"_json_pointer);
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// try to use an array index that is not a number
|
||||
j.contains("/array/one"_json_pointer);
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
<< j.contains("/baz"_json_pointer) << '\n'
|
||||
// an array index with a leading '0' is not found
|
||||
<< j.contains("/array/01"_json_pointer) << '\n'
|
||||
// an array index that is not a number is not found
|
||||
<< j.contains("/array/one"_json_pointer) << std::endl;
|
||||
}
|
||||
@@ -5,3 +5,5 @@ true
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
@@ -1,11 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_array_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, custom_array_type>;
|
||||
using custom_json = nlohmann::json::with_array_t<custom_array_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_binary_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||
std::int64_t, std::uint64_t, double, std::allocator,
|
||||
nlohmann::adl_serializer, custom_binary_type>;
|
||||
using custom_json = nlohmann::json::with_binary_t<custom_binary_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_object_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<custom_object_type, std::vector>;
|
||||
using custom_json = nlohmann::json::with_object_t<custom_object_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_string_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, std::vector, custom_string_type>;
|
||||
using custom_json = nlohmann::json::with_string_t<custom_string_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// an initializer_list_t is what a braced-init-list of JSON values is deduced as
|
||||
json::initializer_list_t init = {"a", 1, 2.0, false};
|
||||
|
||||
json j(init);
|
||||
std::cout << j.dump() << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
["a",1,2.0,false]
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t::binary_t, json::binary_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t::number_float_t, json::number_float_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t::number_integer_t, json::number_integer_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t::number_unsigned_t, json::number_unsigned_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t::string_t, json::string_t>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << std::boolalpha
|
||||
<< std::is_same<json::json_sax_t, nlohmann::json_sax<json>>::value << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
true
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using Map = nlohmann::ordered_map<std::string, int>;
|
||||
|
||||
std::cout << std::boolalpha
|
||||
<< "Container is std::vector<std::pair<const Key, T>>: "
|
||||
<< std::is_same<Map::Container, std::vector<std::pair<const std::string, int>>>::value
|
||||
<< std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Container is std::vector<std::pair<const Key, T>>: true
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
m["one"] = 1;
|
||||
m["two"] = 2;
|
||||
|
||||
// access an existing element
|
||||
std::cout << "m.at(\"one\") = " << m.at("one") << std::endl;
|
||||
|
||||
// modify through the reference returned by at()
|
||||
m.at("two") = 22;
|
||||
std::cout << "m.at(\"two\") = " << m.at("two") << std::endl;
|
||||
|
||||
// accessing a missing key throws
|
||||
try
|
||||
{
|
||||
m.at("three");
|
||||
}
|
||||
catch (const std::out_of_range& e)
|
||||
{
|
||||
std::cout << "exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
m.at("one") = 1
|
||||
m.at("two") = 22
|
||||
exception: key not found
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
m["one"] = 1;
|
||||
|
||||
std::cout << std::boolalpha
|
||||
<< "m.count(\"one\") = " << m.count("one") << '\n'
|
||||
<< "m.count(\"two\") = " << m.count("two") << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
m.count("one") = 1
|
||||
m.count("two") = 0
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, std::string> m;
|
||||
|
||||
// emplace a new element
|
||||
auto res1 = m.emplace("one", "eins");
|
||||
std::cout << std::boolalpha << "inserted: " << res1.second << ", value: " << res1.first->second << std::endl;
|
||||
|
||||
// emplace with an already-existing key: no-op, returns the existing element
|
||||
auto res2 = m.emplace("one", "uno");
|
||||
std::cout << std::boolalpha << "inserted: " << res2.second << ", value: " << res2.first->second << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
inserted: true, value: eins
|
||||
inserted: false, value: eins
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
m["one"] = 1;
|
||||
m["two"] = 2;
|
||||
m["three"] = 3;
|
||||
|
||||
// erase by key
|
||||
std::size_t removed = m.erase("two");
|
||||
std::cout << "removed by key: " << removed << std::endl;
|
||||
|
||||
// erase by iterator
|
||||
m.erase(m.begin());
|
||||
|
||||
std::cout << "remaining: ";
|
||||
for (const auto& element : m)
|
||||
{
|
||||
std::cout << element.first << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
removed by key: 1
|
||||
remaining: three
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
m["one"] = 1;
|
||||
|
||||
auto it = m.find("one");
|
||||
if (it != m.end())
|
||||
{
|
||||
std::cout << "found: " << it->first << " = " << it->second << std::endl;
|
||||
}
|
||||
|
||||
if (m.find("two") == m.end())
|
||||
{
|
||||
std::cout << "\"two\" not found" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
found: one = 1
|
||||
"two" not found
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
|
||||
// insert a single value
|
||||
auto res = m.insert({"one", 1});
|
||||
std::cout << std::boolalpha << "inserted: " << res.second << std::endl;
|
||||
|
||||
// insert a range from another container
|
||||
std::vector<std::pair<const std::string, int>> more = {{"two", 2}, {"three", 3}};
|
||||
m.insert(more.begin(), more.end());
|
||||
|
||||
for (const auto& element : m)
|
||||
{
|
||||
std::cout << element.first << ':' << element.second << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
inserted: true
|
||||
one:1 two:2 three:3
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using Map = nlohmann::ordered_map<std::string, int>;
|
||||
Map::key_compare compare{};
|
||||
|
||||
std::cout << std::boolalpha
|
||||
<< "compare(\"a\", \"a\") = " << compare("a", "a") << '\n'
|
||||
<< "compare(\"a\", \"b\") = " << compare("a", "b") << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
compare("a", "a") = true
|
||||
compare("a", "b") = false
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::ordered_map<std::string, int> m;
|
||||
|
||||
// operator[] inserts a default-constructed value if the key doesn't exist yet
|
||||
m["one"] = 1;
|
||||
std::cout << "m[\"one\"] = " << m["one"] << std::endl;
|
||||
|
||||
// accessing again just returns the existing value
|
||||
std::cout << "m[\"one\"] = " << m["one"] << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
m["one"] = 1
|
||||
m["one"] = 1
|
||||
@@ -8,7 +8,7 @@ int main()
|
||||
try
|
||||
{
|
||||
// parsing input with a syntax error
|
||||
json::parse("[1,2,3,]");
|
||||
json j = json::parse("[1,2,3,]");
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
|
||||
@@ -51,16 +51,16 @@ If you do want to preserve the **insertion order**, you can use the type [`nlohm
|
||||
--8<-- "examples/ordered_json.output"
|
||||
```
|
||||
|
||||
Alternatively, [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) also preserves the insertion order and, unlike [`ordered_map`](../api/ordered_map.md), keeps a lookup index, so it does not have the quadratic cost described below. It is used through a small adapter ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
||||
Alternatively, [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) also preserves the insertion order and, unlike [`ordered_map`](../api/ordered_map/index.md), keeps a lookup index, so it does not have the quadratic cost described below. It is used through a small adapter ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
||||
|
||||
If the order does not matter and you only want faster lookup, `boost::unordered_flat_map`, `absl::flat_hash_map`, `absl::node_hash_map`, and several other hash maps work through an adapter that restores the template argument order `basic_json` expects; see [Template Parameter Requirements](types/template_parameters.md#objecttype). Note these are *unordered*, not insertion-ordered.
|
||||
|
||||
[`tsl::ordered_map`](https://github.com/Tessil/ordered-map) cannot be used: its iterators expose the mapped value as `const`, while `basic_json` needs to modify it in place.
|
||||
|
||||
The [`ordered_map`](../api/ordered_map.md) behind `nlohmann::ordered_json` is deliberately minimal and has no lookup
|
||||
The [`ordered_map`](../api/ordered_map/index.md) behind `nlohmann::ordered_json` is deliberately minimal and has no lookup
|
||||
index, so every key access is a linear scan and building an object of `n` keys costs O(n²). This is unnoticeable at
|
||||
typical object sizes but becomes significant for objects with many thousands of keys; see
|
||||
[`ordered_map` complexity](../api/ordered_map.md#complexity). The alternatives above keep a lookup index and do not
|
||||
[`ordered_map` complexity](../api/ordered_map/index.md#complexity). The alternatives above keep a lookup index and do not
|
||||
have this cost.
|
||||
|
||||
### Notes on parsing
|
||||
|
||||
@@ -88,10 +88,10 @@ whether it is worth the loss of human readability at all -- depends on the actua
|
||||
The default [`json`](../api/json.md) type stores object keys in a `#!cpp std::map`, giving logarithmic-time lookup,
|
||||
insertion, and erasure, at the cost of sorting keys alphabetically rather than preserving insertion order (see
|
||||
[Object Order](object_order.md)). [`ordered_json`](../api/ordered_json.md) uses
|
||||
[`nlohmann::ordered_map`](../api/ordered_map.md) instead, a `#!cpp std::vector`-backed container with no lookup index:
|
||||
[`nlohmann::ordered_map`](../api/ordered_map/index.md) instead, a `#!cpp std::vector`-backed container with no lookup index:
|
||||
every key-based operation is a **linear scan**, so building an object of `n` distinct keys costs **O(n²)** in total --
|
||||
this applies equally to inserting keys one by one and to parsing an object, since the parser inserts each key as it is
|
||||
read. The [measurements on the `ordered_map` page](../api/ordered_map.md#complexity) show this is
|
||||
read. The [measurements on the `ordered_map` page](../api/ordered_map/index.md#complexity) show this is
|
||||
negligible at typical object sizes (2000 keys: 0.7 ms for `json` vs. 3.6 ms for `ordered_json`, a 5x factor) but grows
|
||||
steeply for large, machine-generated objects (16 000 keys: 3.3 ms vs. 181.6 ms, a 54x factor).
|
||||
|
||||
|
||||
@@ -351,9 +351,8 @@ The number types can be changed with template parameters.
|
||||
|
||||
A `basic_json` type that uses `#!c long double` as floating-point type.
|
||||
|
||||
```cpp hl_lines="2"
|
||||
using json_ld = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||
std::int64_t, std::uint64_t, long double>;
|
||||
```cpp hl_lines="1"
|
||||
using json_ld = nlohmann::json::with_float_t<long double>;
|
||||
```
|
||||
|
||||
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse
|
||||
|
||||
@@ -8,6 +8,10 @@ these requirements so they do not have to be discovered by trial and error. Each
|
||||
that are known to work for that parameter and the ones that do not, checked against Boost 1.83, Abseil 20250127.0,
|
||||
Folly, EASTL 3.21, `ankerl::unordered_dense`, `phmap`, `gtl`, `robin_hood`, `tsl::ordered_map`, and Qt 6.
|
||||
|
||||
To change a single template parameter and keep the others, use the member alias templates
|
||||
[`with_*_t`](../../api/basic_json/with_t.md); for instance, `nlohmann::json::with_float_t<long double>` is `json` with
|
||||
`#!cpp long double` as [`number_float_t`](../../api/basic_json/number_float_t.md).
|
||||
|
||||
## How to read this page
|
||||
|
||||
Requirements are split into two groups:
|
||||
@@ -38,7 +42,7 @@ Requirements are split into two groups:
|
||||
|
||||
| Template parameter | Default | Notable substitutes |
|
||||
|-------------------------------------------------------------------|-----------------------------------|-----------------------------------------------------------------------|
|
||||
| [`ObjectType`](#objecttype) | `std::map` | [`nlohmann::ordered_map`](../../api/ordered_map.md), Abseil hash maps |
|
||||
| [`ObjectType`](#objecttype) | `std::map` | [`nlohmann::ordered_map`](../../api/ordered_map/index.md), Abseil hash maps |
|
||||
| [`ArrayType`](#arraytype) | `std::vector` | `#!cpp std::deque` |
|
||||
| [`StringType`](#stringtype) | `std::string` | `std::string`-like types over `char` |
|
||||
| [`BooleanType`](#booleantype) | `bool` | none worth using |
|
||||
@@ -143,7 +147,7 @@ struct unordered_map_object
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
using unordered_json = nlohmann::basic_json<unordered_map_object>;
|
||||
using unordered_json = nlohmann::json::with_object_t<unordered_map_object>;
|
||||
```
|
||||
|
||||
Whether `#!cpp std::unordered_map` can be instantiated at all depends on the standard library: `object_t` is formed
|
||||
@@ -176,7 +180,7 @@ struct flat_hash_object
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
using flat_hash_json = nlohmann::basic_json<flat_hash_object>;
|
||||
using flat_hash_json = nlohmann::json::with_object_t<flat_hash_object>;
|
||||
```
|
||||
|
||||
`absl::node_hash_map` keeps references to the mapped values valid across insertions; `absl::flat_hash_map` does not,
|
||||
@@ -231,7 +235,7 @@ The library does not sort or de-duplicate keys itself; the behavior described in
|
||||
| Container | Notes |
|
||||
|----------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
|
||||
| `#!cpp std::map` (default) | |
|
||||
| [`nlohmann::ordered_map`](../../api/ordered_map.md) | used by [`ordered_json`](../../api/ordered_json.md); keeps insertion order |
|
||||
| [`nlohmann::ordered_map`](../../api/ordered_map/index.md) | used by [`ordered_json`](../../api/ordered_json.md); keeps insertion order |
|
||||
| [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) | keeps insertion order; adapter puts `fifo_map_compare` in the comparator slot |
|
||||
| `boost::container::map`, `boost::container::flat_map` | no adapter needed |
|
||||
| `#!cpp std::unordered_map` | through the adapter above; not with libstdc++ 9, see the note |
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -50,7 +50,7 @@ The public headers are in [`include/nlohmann`](https://github.com/nlohmann/json/
|
||||
- [`adl_serializer.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/adl_serializer.hpp), [`byte_container_with_subtype.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/byte_container_with_subtype.hpp), and [`ordered_map.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/ordered_map.hpp) define
|
||||
[`adl_serializer`](../api/adl_serializer/index.md),
|
||||
[`byte_container_with_subtype`](../api/byte_container_with_subtype/index.md), and
|
||||
[`ordered_map`](../api/ordered_map.md).
|
||||
[`ordered_map`](../api/ordered_map/index.md).
|
||||
|
||||
Everything else lives in [`detail/`](https://github.com/nlohmann/json/tree/develop/include/nlohmann/detail) and namespace `nlohmann::detail`, which is not part of the public API. Paths
|
||||
below are relative to `include/nlohmann`.
|
||||
@@ -97,7 +97,7 @@ is generated from these files with `make amalgamate` and must not be edited by h
|
||||
The library provides two specializations:
|
||||
|
||||
- [`json`](../api/json.md) uses all default template arguments.
|
||||
- [`ordered_json`](../api/ordered_json.md) uses [`ordered_map`](../api/ordered_map.md) as `ObjectType` to keep the
|
||||
- [`ordered_json`](../api/ordered_json.md) uses [`ordered_map`](../api/ordered_map/index.md) as `ObjectType` to keep the
|
||||
insertion order of object keys.
|
||||
|
||||
The requirements on the template arguments are listed in
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
This page summarizes the notable changes of every release and links to the relevant documentation.
|
||||
The **complete release notes** — including all changes, the download files, and their checksums — are
|
||||
published on the [GitHub releases page](https://github.com/nlohmann/json/releases).
|
||||
published on the [GitHub releases page](https://github.com/nlohmann/json/releases). For a raw,
|
||||
signature-level diff of the public API between releases, see [API Changes](api_changes.md).
|
||||
|
||||
!!! info "Unreleased changes"
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ function to use instead.
|
||||
=== "Deprecated"
|
||||
|
||||
```cpp
|
||||
using my_json = nlohmann::basic_json<std::map, std::vector, my_string_type>;
|
||||
using my_json = nlohmann::json::with_string_t<my_string_type>;
|
||||
nlohmann::json_pointer<my_json> ptr("/foo/bar/1");
|
||||
```
|
||||
|
||||
|
||||
+28
-1
@@ -52,6 +52,7 @@ nav:
|
||||
- "FAQ": home/faq.md
|
||||
- home/exceptions.md
|
||||
- home/releases.md
|
||||
- home/api_changes.md
|
||||
- home/design_goals.md
|
||||
- home/architecture.md
|
||||
- home/customers.md
|
||||
@@ -123,6 +124,7 @@ nav:
|
||||
- 'begin': api/basic_json/begin.md
|
||||
- 'binary': api/basic_json/binary.md
|
||||
- 'binary_t': api/basic_json/binary_t.md
|
||||
- 'bjdata_version_t': api/basic_json/bjdata_version_t.md
|
||||
- 'boolean_t': api/basic_json/boolean_t.md
|
||||
- 'cbegin': api/basic_json/cbegin.md
|
||||
- 'cbor_tag_handler_t': api/basic_json/cbor_tag_handler_t.md
|
||||
@@ -161,6 +163,7 @@ nav:
|
||||
- 'get_to': api/basic_json/get_to.md
|
||||
- 'std::formatter<basic_json>': api/basic_json/std_formatter.md
|
||||
- 'std::hash<basic_json>': api/basic_json/std_hash.md
|
||||
- 'initializer_list_t': api/basic_json/initializer_list_t.md
|
||||
- 'input_format_t': api/basic_json/input_format_t.md
|
||||
- 'insert': api/basic_json/insert.md
|
||||
- 'invalid_iterator': api/basic_json/invalid_iterator.md
|
||||
@@ -179,6 +182,7 @@ nav:
|
||||
- 'is_structured': api/basic_json/is_structured.md
|
||||
- 'items': api/basic_json/items.md
|
||||
- 'json_base_class_t': api/basic_json/json_base_class_t.md
|
||||
- 'json_sax_t': api/basic_json/json_sax_t.md
|
||||
- 'json_serializer': api/basic_json/json_serializer.md
|
||||
- 'max_size': api/basic_json/max_size.md
|
||||
- 'meta': api/basic_json/meta.md
|
||||
@@ -237,11 +241,13 @@ nav:
|
||||
- 'Overview': api/byte_container_with_subtype/index.md
|
||||
- '(constructor)': api/byte_container_with_subtype/byte_container_with_subtype.md
|
||||
- 'clear_subtype': api/byte_container_with_subtype/clear_subtype.md
|
||||
- 'container_type': api/byte_container_with_subtype/container_type.md
|
||||
- 'has_subtype': api/byte_container_with_subtype/has_subtype.md
|
||||
- 'operator==': api/byte_container_with_subtype/operator_eq.md
|
||||
- 'operator!=': api/byte_container_with_subtype/operator_ne.md
|
||||
- 'set_subtype': api/byte_container_with_subtype/set_subtype.md
|
||||
- 'subtype': api/byte_container_with_subtype/subtype.md
|
||||
- 'subtype_type': api/byte_container_with_subtype/subtype_type.md
|
||||
- adl_serializer:
|
||||
- 'Overview': api/adl_serializer/index.md
|
||||
- 'from_json': api/adl_serializer/from_json.md
|
||||
@@ -268,25 +274,46 @@ nav:
|
||||
- 'to_string': api/json_pointer/to_string.md
|
||||
- json_sax:
|
||||
- 'Overview': api/json_sax/index.md
|
||||
- '(Constructor)': api/json_sax/json_sax.md
|
||||
- '(Destructor)': api/json_sax/~json_sax.md
|
||||
- 'operator=': api/json_sax/operator=.md
|
||||
- 'binary': api/json_sax/binary.md
|
||||
- 'binary_t': api/json_sax/binary_t.md
|
||||
- 'boolean': api/json_sax/boolean.md
|
||||
- 'end_array': api/json_sax/end_array.md
|
||||
- 'end_object': api/json_sax/end_object.md
|
||||
- 'key': api/json_sax/key.md
|
||||
- 'null': api/json_sax/null.md
|
||||
- 'number_float': api/json_sax/number_float.md
|
||||
- 'number_float_t': api/json_sax/number_float_t.md
|
||||
- 'number_integer': api/json_sax/number_integer.md
|
||||
- 'number_integer_t': api/json_sax/number_integer_t.md
|
||||
- 'number_unsigned': api/json_sax/number_unsigned.md
|
||||
- 'number_unsigned_t': api/json_sax/number_unsigned_t.md
|
||||
- 'parse_error': api/json_sax/parse_error.md
|
||||
- 'start_array': api/json_sax/start_array.md
|
||||
- 'start_object': api/json_sax/start_object.md
|
||||
- 'string': api/json_sax/string.md
|
||||
- 'string_t': api/json_sax/string_t.md
|
||||
- 'operator<<(basic_json), operator<<(json_pointer)': api/operator_ltlt.md
|
||||
- 'operator>>(basic_json)': api/operator_gtgt.md
|
||||
- 'operator""_json': api/operator_literal_json.md
|
||||
- 'operator""_json_pointer': api/operator_literal_json_pointer.md
|
||||
- 'ordered_json': api/ordered_json.md
|
||||
- 'ordered_map': api/ordered_map.md
|
||||
- ordered_map:
|
||||
- 'Overview': api/ordered_map/index.md
|
||||
- '(Constructor)': api/ordered_map/ordered_map.md
|
||||
- '(Destructor)': api/ordered_map/~ordered_map.md
|
||||
- 'operator=': api/ordered_map/operator=.md
|
||||
- 'at': api/ordered_map/at.md
|
||||
- 'Container': api/ordered_map/Container.md
|
||||
- 'count': api/ordered_map/count.md
|
||||
- 'emplace': api/ordered_map/emplace.md
|
||||
- 'erase': api/ordered_map/erase.md
|
||||
- 'find': api/ordered_map/find.md
|
||||
- 'insert': api/ordered_map/insert.md
|
||||
- 'key_compare': api/ordered_map/key_compare.md
|
||||
- 'operator[]': api/ordered_map/operator[].md
|
||||
- macros:
|
||||
- 'Overview': api/macros/index.md
|
||||
- 'JSON_ASSERT': api/macros/json_assert.md
|
||||
|
||||
@@ -22,7 +22,9 @@ template<typename BinaryType>
|
||||
class byte_container_with_subtype : public BinaryType
|
||||
{
|
||||
public:
|
||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/container_type/
|
||||
using container_type = BinaryType;
|
||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype_type/
|
||||
using subtype_type = std::uint64_t;
|
||||
|
||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||
@@ -54,12 +56,14 @@ class byte_container_with_subtype : public BinaryType
|
||||
, m_has_subtype(true)
|
||||
{}
|
||||
|
||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/operator_eq/
|
||||
bool operator==(const byte_container_with_subtype& rhs) const
|
||||
{
|
||||
return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
|
||||
std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
|
||||
}
|
||||
|
||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/operator_ne/
|
||||
bool operator!=(const byte_container_with_subtype& rhs) const
|
||||
{
|
||||
return !(rhs == *this);
|
||||
|
||||
@@ -9,12 +9,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
#if !defined(__SIZEOF_INT128__) && defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
#include <intrin0.h> // __umulh, _umul128
|
||||
#endif
|
||||
|
||||
#include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
// Portable bit-level helpers for the number and string scanners. They use
|
||||
// compiler builtins where available and plain C++ otherwise, so they need no
|
||||
// platform headers and work regardless of byte order.
|
||||
// compiler builtins or platform-specific intrinsics where available and plain
|
||||
// C++ otherwise, so they work regardless of byte order.
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
@@ -52,6 +55,12 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
||||
__extension__ using uint128 = unsigned __int128;
|
||||
const uint128 r = static_cast<uint128>(a) * b;
|
||||
return {static_cast<std::uint64_t>(r), static_cast<std::uint64_t>(r >> 64u)};
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
std::uint64_t high = 0;
|
||||
const std::uint64_t low = _umul128(a, b, &high);
|
||||
return {low, high};
|
||||
#elif defined(_MSC_VER) && defined(_M_ARM64)
|
||||
return {a * b, __umulh(a, b)};
|
||||
#else
|
||||
const std::uint64_t a_lo = a & 0xFFFFFFFFu;
|
||||
const std::uint64_t a_hi = a >> 32u;
|
||||
|
||||
@@ -34,15 +34,21 @@ input.
|
||||
template<typename BasicJsonType>
|
||||
struct json_sax
|
||||
{
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/number_integer_t/
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/number_unsigned_t/
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/number_float_t/
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/string_t/
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/binary_t/
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
|
||||
/*!
|
||||
@brief a null value was read
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/null/
|
||||
*/
|
||||
virtual bool null() = 0;
|
||||
|
||||
@@ -50,6 +56,7 @@ struct json_sax
|
||||
@brief a boolean value was read
|
||||
@param[in] val boolean value
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/boolean/
|
||||
*/
|
||||
virtual bool boolean(bool val) = 0;
|
||||
|
||||
@@ -57,6 +64,7 @@ struct json_sax
|
||||
@brief an integer number was read
|
||||
@param[in] val integer value
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/number_integer/
|
||||
*/
|
||||
virtual bool number_integer(number_integer_t val) = 0;
|
||||
|
||||
@@ -64,6 +72,7 @@ struct json_sax
|
||||
@brief an unsigned integer number was read
|
||||
@param[in] val unsigned integer value
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/number_unsigned/
|
||||
*/
|
||||
virtual bool number_unsigned(number_unsigned_t val) = 0;
|
||||
|
||||
@@ -72,6 +81,7 @@ struct json_sax
|
||||
@param[in] val floating-point value
|
||||
@param[in] s raw token value
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/number_float/
|
||||
*/
|
||||
virtual bool number_float(number_float_t val, const string_t& s) = 0;
|
||||
|
||||
@@ -80,6 +90,7 @@ struct json_sax
|
||||
@param[in] val string value
|
||||
@return whether parsing should proceed
|
||||
@note It is safe to move the passed string value.
|
||||
@sa https://json.nlohmann.me/api/json_sax/string/
|
||||
*/
|
||||
virtual bool string(string_t& val) = 0;
|
||||
|
||||
@@ -88,6 +99,7 @@ struct json_sax
|
||||
@param[in] val binary value
|
||||
@return whether parsing should proceed
|
||||
@note It is safe to move the passed binary value.
|
||||
@sa https://json.nlohmann.me/api/json_sax/binary/
|
||||
*/
|
||||
virtual bool binary(binary_t& val) = 0;
|
||||
|
||||
@@ -96,6 +108,7 @@ struct json_sax
|
||||
@param[in] elements number of object elements or -1 if unknown
|
||||
@return whether parsing should proceed
|
||||
@note binary formats may report the number of elements
|
||||
@sa https://json.nlohmann.me/api/json_sax/start_object/
|
||||
*/
|
||||
virtual bool start_object(std::size_t elements) = 0;
|
||||
|
||||
@@ -104,12 +117,14 @@ struct json_sax
|
||||
@param[in] val object key
|
||||
@return whether parsing should proceed
|
||||
@note It is safe to move the passed string.
|
||||
@sa https://json.nlohmann.me/api/json_sax/key/
|
||||
*/
|
||||
virtual bool key(string_t& val) = 0;
|
||||
|
||||
/*!
|
||||
@brief the end of an object was read
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/end_object/
|
||||
*/
|
||||
virtual bool end_object() = 0;
|
||||
|
||||
@@ -118,12 +133,14 @@ struct json_sax
|
||||
@param[in] elements number of array elements or -1 if unknown
|
||||
@return whether parsing should proceed
|
||||
@note binary formats may report the number of elements
|
||||
@sa https://json.nlohmann.me/api/json_sax/start_array/
|
||||
*/
|
||||
virtual bool start_array(std::size_t elements) = 0;
|
||||
|
||||
/*!
|
||||
@brief the end of an array was read
|
||||
@return whether parsing should proceed
|
||||
@sa https://json.nlohmann.me/api/json_sax/end_array/
|
||||
*/
|
||||
virtual bool end_array() = 0;
|
||||
|
||||
@@ -133,16 +150,23 @@ struct json_sax
|
||||
@param[in] last_token the last read token
|
||||
@param[in] ex an exception object describing the error
|
||||
@return whether parsing should proceed (must return false)
|
||||
@sa https://json.nlohmann.me/api/json_sax/parse_error/
|
||||
*/
|
||||
virtual bool parse_error(std::size_t position,
|
||||
const std::string& last_token,
|
||||
const detail::exception& ex) = 0;
|
||||
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/json_sax/
|
||||
json_sax() = default;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/json_sax/
|
||||
json_sax(const json_sax&) = default;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/json_sax/
|
||||
json_sax(json_sax&&) noexcept = default;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/operator=/
|
||||
json_sax& operator=(const json_sax&) = default;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/operator=/
|
||||
json_sax& operator=(json_sax&&) noexcept = default;
|
||||
/// @sa https://json.nlohmann.me/api/json_sax/~json_sax/
|
||||
virtual ~json_sax() = default;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include <iosfwd> // ostream
|
||||
#endif // JSON_NO_IO
|
||||
#include <limits> // max
|
||||
#include <map> // map
|
||||
#include <numeric> // accumulate
|
||||
#include <set> // set
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
@@ -57,6 +57,7 @@ class json_pointer
|
||||
|
||||
public:
|
||||
// for backwards compatibility accept BasicJsonType
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/string_t/
|
||||
using string_t = typename string_t_helper<RefStringType>::type;
|
||||
|
||||
/// @brief create JSON pointer
|
||||
@@ -359,33 +360,82 @@ class json_pointer
|
||||
|
||||
private:
|
||||
/*!
|
||||
@brief the reference token sequences that denote arrays
|
||||
@brief the pointer prefixes of a flattened object, and which of them denote arrays
|
||||
|
||||
@ref unflatten collects the pointer prefixes that have a reference token 0
|
||||
among their children; @ref get_and_create creates arrays exactly below
|
||||
those prefixes and objects everywhere else. Deciding this up front keeps
|
||||
the result independent of the order in which the flattened object is
|
||||
iterated, which is unspecified for some object types.
|
||||
|
||||
The prefixes form a tree and are numbered, so each of them is stored only
|
||||
once (as a node) rather than as a copy of all of its reference tokens.
|
||||
*/
|
||||
using array_parents_t = std::set<std::vector<string_t>>;
|
||||
struct prefix_tree
|
||||
{
|
||||
// children[id] maps a reference token to the number of the prefix
|
||||
// extended by that token; number 0 is the empty prefix
|
||||
std::vector<std::map<string_t, std::size_t>> children;
|
||||
// is_array[id] is true iff some flattened key has the reference token
|
||||
// 0 directly below the prefix with number id
|
||||
std::vector<bool> is_array;
|
||||
|
||||
// start with the empty prefix only
|
||||
prefix_tree()
|
||||
: children(1)
|
||||
, is_array(1, false)
|
||||
{}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, adding it if it is new
|
||||
std::size_t add_child(std::size_t id, string_t&& reference_token)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
is_array[id] = true;
|
||||
}
|
||||
|
||||
// read the number before the emplace_back below, which may
|
||||
// reallocate children and invalidate the iterator
|
||||
const std::size_t next = children.size();
|
||||
const auto inserted = children[id].emplace(std::move(reference_token), next);
|
||||
const std::size_t child = inserted.first->second;
|
||||
if (inserted.second)
|
||||
{
|
||||
children.emplace_back();
|
||||
is_array.push_back(false);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, which must have been added before
|
||||
std::size_t find_child(std::size_t id, const string_t& reference_token) const
|
||||
{
|
||||
const auto it = children[id].find(reference_token);
|
||||
JSON_ASSERT(it != children[id].end());
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief create and return a reference to the pointed to value
|
||||
|
||||
Complexity: Linear in the number of reference tokens.
|
||||
Complexity: Linear in the number of reference tokens (times the logarithm
|
||||
of the number of siblings for the prefix lookup).
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if array index is not a number
|
||||
@throw type_error.313 if value cannot be unflattened
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const array_parents_t& array_parents) const
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const prefix_tree& tree) const
|
||||
{
|
||||
auto* result = &j;
|
||||
|
||||
// the reference tokens that have been consumed so far; used to look up
|
||||
// whether the value to be created below is an array or an object
|
||||
std::vector<string_t> prefix;
|
||||
// the number of the prefix consumed so far; used to look up whether
|
||||
// the value to be created below is an array or an object
|
||||
std::size_t id = 0;
|
||||
|
||||
// in case no reference tokens exist, return a reference to the JSON value
|
||||
// j which will be overwritten by a primitive value
|
||||
@@ -395,7 +445,7 @@ class json_pointer
|
||||
{
|
||||
case detail::value_t::null:
|
||||
{
|
||||
if (array_parents.find(prefix) != array_parents.end())
|
||||
if (tree.is_array[id])
|
||||
{
|
||||
// some reference token below this position is 0, so the
|
||||
// value is an array
|
||||
@@ -440,7 +490,7 @@ class json_pointer
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
|
||||
}
|
||||
|
||||
prefix.push_back(reference_token);
|
||||
id = tree.find_child(id, reference_token);
|
||||
}
|
||||
|
||||
return *result;
|
||||
@@ -878,64 +928,131 @@ class json_pointer
|
||||
@param[in,out] result the result object to insert values to
|
||||
|
||||
@note Empty objects or arrays are flattened to `null`.
|
||||
|
||||
The value is walked with an explicit stack rather than the call stack, so
|
||||
arbitrarily deeply nested values can be flattened.
|
||||
|
||||
@sa https://github.com/nlohmann/json/issues/5393
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
static void flatten(const string_t& reference_string,
|
||||
const BasicJsonType& value,
|
||||
BasicJsonType& result)
|
||||
{
|
||||
switch (value.type())
|
||||
using object_const_iterator = typename BasicJsonType::object_t::const_iterator;
|
||||
|
||||
// an array or object being walked: the container, the array index or
|
||||
// object iterator of the next child, and the length of the path of the
|
||||
// container itself
|
||||
struct frame
|
||||
{
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (value.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate array and use index as a reference string
|
||||
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
|
||||
value.m_data.m_value.array->operator[](i), result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
frame(const BasicJsonType* container_, object_const_iterator member_, const std::size_t path_length_) noexcept
|
||||
: container(container_), member(std::move(member_)), path_length(path_length_)
|
||||
{}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (value.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate object and use keys as reference string
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
const BasicJsonType* container;
|
||||
std::size_t index = 0;
|
||||
object_const_iterator member;
|
||||
std::size_t path_length;
|
||||
};
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
// The containers being flattened are kept on an explicit stack, and
|
||||
// every child is flattened completely before the next one, so the
|
||||
// entries come out in the same order as with a recursive walk. The
|
||||
// path of the value being flattened is kept in one buffer that grows
|
||||
// and shrinks with the stack, rather than in a new string per level.
|
||||
std::vector<frame> stack;
|
||||
string_t path = reference_string;
|
||||
|
||||
// flatten `v`, whose path is `path`: primitives and empty containers
|
||||
// are added to the result right away; other containers get a frame
|
||||
const auto enter = [&stack, &path, &result](const BasicJsonType & v)
|
||||
{
|
||||
switch (v.type())
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[reference_string] = value;
|
||||
break;
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (v.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, object_const_iterator(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (v.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, v.m_data.m_value.object->begin(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[path] = v;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enter(value);
|
||||
while (!stack.empty())
|
||||
{
|
||||
// the frame is changed through stack.back(): enter() may push a
|
||||
// frame, which would invalidate a reference to it
|
||||
const BasicJsonType* const container = stack.back().container;
|
||||
|
||||
// drop the path of the previous child
|
||||
path.resize(stack.back().path_length);
|
||||
|
||||
if (container->is_array())
|
||||
{
|
||||
const auto& array = *container->m_data.m_value.array;
|
||||
const std::size_t i = stack.back().index;
|
||||
if (i == array.size())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate array and use index as a reference string
|
||||
++stack.back().index;
|
||||
detail::concat_into(path, '/', detail::to_string<string_t>(i));
|
||||
enter(array[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const object_const_iterator it = stack.back().member;
|
||||
if (it == container->m_data.m_value.object->end())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate object and use keys as reference string
|
||||
++stack.back().member;
|
||||
detail::concat_into(path, '/', detail::escape(it->first));
|
||||
enter(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -963,19 +1080,15 @@ class json_pointer
|
||||
|
||||
// collect the pointer prefixes that have a reference token 0 among
|
||||
// their children; the values below them are arrays, all others are
|
||||
// objects (see array_parents_t)
|
||||
array_parents_t array_parents;
|
||||
// objects (see prefix_tree)
|
||||
prefix_tree tree;
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
json_pointer ptr(element.first);
|
||||
std::vector<string_t> prefix;
|
||||
std::size_t id = 0;
|
||||
for (auto& reference_token : ptr.reference_tokens)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
array_parents.insert(prefix);
|
||||
}
|
||||
prefix.push_back(std::move(reference_token));
|
||||
id = tree.add_child(id, std::move(reference_token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,7 +1104,7 @@ class json_pointer
|
||||
// that if the JSON pointer is "" (i.e., points to the whole value),
|
||||
// function get_and_create returns a reference to the result itself.
|
||||
// An assignment will then create a primitive value.
|
||||
json_pointer(element.first).get_and_create(result, array_parents) = element.second;
|
||||
json_pointer(element.first).get_and_create(result, tree) = element.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -85,6 +85,12 @@ template<typename BasicJsonType, typename CharType, typename OutputSinkType = ou
|
||||
class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
|
||||
/// an object key as string_t: a reference when object_t::key_type already is
|
||||
/// string_t, otherwise a converted copy that outlives sanitize_utf8_for_write's result
|
||||
using object_key_string_t = typename std::conditional <
|
||||
std::is_same<typename BasicJsonType::object_t::key_type, string_t>::value,
|
||||
const string_t&, string_t >::type;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
@@ -244,16 +250,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, value.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_cbor_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -316,23 +313,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_cbor_head(0xA0, j.m_data.m_value.object->size());
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// el.first is checked here, against the object as
|
||||
// diagnostics context, because write_cbor(el.first)
|
||||
// converts it to a temporary basic_json that would be
|
||||
// used as the context instead; for error_handler_t::keep
|
||||
// and ::replace/::ignore the recursive write_cbor(el.first)
|
||||
// call below handles the key like any other string, so no
|
||||
// separate check is needed here for those
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_cbor(el.first);
|
||||
// el.first is written directly (not via a temporary
|
||||
// basic_json), with the object as diagnostics context
|
||||
write_cbor_string(el.first, j);
|
||||
write_cbor(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -491,39 +485,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(value.size(), j);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_msgpack_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -629,19 +591,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_msgpack_object_prefix(j.m_data.m_value.object->size(), j);
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// as in write_cbor, el.first is checked here against the
|
||||
// object as diagnostics context; the recursive call below
|
||||
// handles keep/replace/ignore like any other string
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_msgpack(el.first);
|
||||
// as in write_cbor, el.first is written directly with the
|
||||
// object as diagnostics context
|
||||
write_msgpack_string(el.first, j);
|
||||
write_msgpack(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -819,8 +782,10 @@ class binary_writer
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = el.first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(el.first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -1025,13 +990,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// el.first is checked here, against the object as diagnostics
|
||||
// context, like the matching check in write_cbor's object case
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_cbor(current.object_it->first);
|
||||
// the key is written directly (not via a temporary basic_json),
|
||||
// with the object as diagnostics context, as in write_cbor
|
||||
write_cbor_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_cbor_value_or_push(*child, stack);
|
||||
@@ -1106,11 +1067,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_msgpack(current.object_it->first);
|
||||
// as in write_cbor_iterative, the key is written directly with
|
||||
// the object as diagnostics context
|
||||
write_msgpack_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_msgpack_value_or_push(*child, stack);
|
||||
@@ -1366,8 +1325,10 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = current.object_it->first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(current.object_it->first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -1988,6 +1949,85 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief write a CBOR text string
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context (the string value itself, or the object a key belongs to) used
|
||||
as diagnostics context; this avoids converting object keys to a temporary
|
||||
basic_json just to write them
|
||||
|
||||
@note When object_t::key_type is not string_t, @a value is a temporary
|
||||
string_t converted from the key, which lives only until the end of
|
||||
the caller's statement. The reference returned by
|
||||
@ref sanitize_utf8_for_write may refer to it, so it must not escape
|
||||
this function.
|
||||
*/
|
||||
void write_cbor_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, sanitized.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
/////////////
|
||||
// MsgPack //
|
||||
/////////////
|
||||
|
||||
/*!
|
||||
@brief write a MessagePack str
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context used as diagnostics context, as in @ref write_cbor_string
|
||||
|
||||
@note As in @ref write_cbor_string, @a value may be a temporary string_t
|
||||
converted from a key, so the reference returned by
|
||||
@ref sanitize_utf8_for_write must not escape this function.
|
||||
*/
|
||||
void write_msgpack_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(sanitized.size(), context);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
////////////
|
||||
// UBJSON //
|
||||
////////////
|
||||
@@ -2730,6 +2770,11 @@ class binary_writer
|
||||
itself in every case but a sanitized `replace`/`ignore` one, so @a
|
||||
storage must outlive the returned reference only then.
|
||||
|
||||
@a s must be an lvalue that outlives the returned reference. An object key
|
||||
whose `key_type` is not @ref string_t must therefore first be converted
|
||||
into a named string_t (see @ref object_key_string_t); the deleted overload
|
||||
below enforces this at compile time.
|
||||
|
||||
@param[in] s the string (value or object key) to write
|
||||
@param[in] context the value @a s belongs to (for diagnostics)
|
||||
@param[out] storage backing storage for a sanitized copy
|
||||
@@ -2759,6 +2804,10 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/// deleted: anything but a string_t would bind a temporary that dies before the returned reference is used
|
||||
template < typename T, enable_if_t < !std::is_same<T, string_t>::value, int > = 0 >
|
||||
const string_t& sanitize_utf8_for_write(const T& /*s*/, const BasicJsonType& /*context*/, string_t& /*storage*/) const = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete): a private helper's guard, not part of the interface
|
||||
|
||||
/*!
|
||||
@brief write an integer in the shortest encoding
|
||||
|
||||
|
||||
@@ -108,8 +108,8 @@ void encode_utf8(std::uint32_t cp, const Out& out)
|
||||
///////////////////
|
||||
|
||||
// UTF-8 decoder states used by decode() below
|
||||
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
|
||||
/*!
|
||||
@brief process a byte of a UTF-8 sequence
|
||||
|
||||
Loaded 100 of 163 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user