mirror of
https://github.com/nlohmann/json.git
synced 2026-08-28 03:53:20 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e76bf426 | ||
|
|
1876493f87 | ||
|
|
01853ed6bc | ||
|
|
2f025f401e | ||
|
|
734fd305a1 | ||
|
|
36187cacfb | ||
|
|
b5378e8deb |
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -67,8 +67,18 @@ jobs:
|
||||
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
|
||||
$INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp
|
||||
|
||||
# fail loudly if a directory is renamed or removed: find would only warn
|
||||
# about the missing path and silently drop its files from the check
|
||||
SOURCE_DIRS="docs/mkdocs/docs/examples include tests"
|
||||
for DIR in $SOURCE_DIRS; do
|
||||
if [ ! -d "$DIR" ]; then
|
||||
echo "::error::source directory '$DIR' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
|
||||
$(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
|
||||
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
|
||||
|
||||
- name: Build patch and check for differences
|
||||
id: diff
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ on:
|
||||
- develop
|
||||
paths:
|
||||
- docs/mkdocs/**
|
||||
- docs/examples/**
|
||||
workflow_dispatch:
|
||||
|
||||
# we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications
|
||||
@@ -27,7 +26,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
target: [ci_test_amalgamation, ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind]
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -369,7 +369,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -392,7 +392,7 @@ jobs:
|
||||
target: [ci_test_examples, ci_test_build_documentation]
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
+1
-1
@@ -294,7 +294,7 @@ file(GLOB_RECURSE INDENT_FILES
|
||||
${PROJECT_SOURCE_DIR}/tests/src/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/tests/src/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
|
||||
${PROJECT_SOURCE_DIR}/docs/examples/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
||||
)
|
||||
|
||||
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
||||
|
||||
@@ -52,6 +52,11 @@ optional, `#!cpp bjdata_version_t::draft2` by default.
|
||||
|
||||
Strong guarantee: if an exception is thrown, there are no changes in the JSON value.
|
||||
|
||||
## Exceptions
|
||||
|
||||
- Throws [`other_error.502`](../../home/exceptions.md#jsonexceptionother_error502) if `use_type` is true and `use_size`
|
||||
is false.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the size of the JSON value `j`.
|
||||
|
||||
@@ -45,6 +45,11 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
|
||||
Strong guarantee: if an exception is thrown, there are no changes in the JSON value.
|
||||
|
||||
## Exceptions
|
||||
|
||||
- Throws [`other_error.502`](../../home/exceptions.md#jsonexceptionother_error502) if `use_type` is true and `use_size`
|
||||
is false.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the size of the JSON value `j`.
|
||||
|
||||
@@ -9,13 +9,13 @@ int main()
|
||||
auto text = R"({"IDs": [116, 943], "Width": 800})";
|
||||
|
||||
// discard the array when the parser reads its opening bracket
|
||||
json j_array_start = json::parse(text, [](int /*depth*/, json::parse_event_t event, json & /*parsed*/)
|
||||
json j_array_start = json::parse(text, [](int /*depth*/, json::parse_event_t event, json& /*parsed*/)
|
||||
{
|
||||
return event != json::parse_event_t::array_start;
|
||||
});
|
||||
|
||||
// discard the same array when the parser reads its closing bracket
|
||||
json j_array_end = json::parse(text, [](int /*depth*/, json::parse_event_t event, json & /*parsed*/)
|
||||
json j_array_end = json::parse(text, [](int /*depth*/, json::parse_event_t event, json& /*parsed*/)
|
||||
{
|
||||
return event != json::parse_event_t::array_end;
|
||||
});
|
||||
@@ -33,7 +33,7 @@ int main()
|
||||
});
|
||||
|
||||
// discard the top-level object
|
||||
json j_root = json::parse(text, [](int /*depth*/, json::parse_event_t event, json & /*parsed*/)
|
||||
json j_root = json::parse(text, [](int /*depth*/, json::parse_event_t event, json& /*parsed*/)
|
||||
{
|
||||
return event != json::parse_event_t::object_end;
|
||||
});
|
||||
|
||||
@@ -98,6 +98,17 @@ The library maps BSON record types to JSON value types as follows:
|
||||
This library deserializes BSON type `0x11` (Timestamp) as a `number_unsigned` value. The 64-bit value is preserved,
|
||||
but the Timestamp type information is not.
|
||||
|
||||
!!! warning "Lenient BSON input handling"
|
||||
|
||||
The BSON reader is lenient in a few areas where the BSON specification is more restrictive:
|
||||
|
||||
- array element keys are not checked against the required decimal sequence (`0`, `1`, `2`, ...),
|
||||
- any non-zero byte is accepted as `true` for the boolean type, and
|
||||
- the payload for binary subtype `0x02` is returned as-is, including its inner length prefix.
|
||||
|
||||
If BSON input must be validated for strict specification compliance, validate it separately before passing it to
|
||||
`from_bson()`.
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
|
||||
@@ -160,14 +160,11 @@ The library maps CBOR types to JSON value types as follows:
|
||||
|
||||
The mapping is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors:
|
||||
|
||||
- date/time (0xC0..0xC1)
|
||||
- bignum (0xC2..0xC3)
|
||||
- decimal fraction (0xC4)
|
||||
- bigfloat (0xC5)
|
||||
- expected conversions (0xD5..0xD7)
|
||||
- simple values (0xE0..0xF3, 0xF8)
|
||||
- undefined (0xF7)
|
||||
|
||||
Tagged items (0xC0..0xDB) are not interpreted either; see the note on tagged items below.
|
||||
|
||||
!!! warning "Negative integer overflow"
|
||||
|
||||
CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the
|
||||
@@ -181,7 +178,7 @@ The library maps CBOR types to JSON value types as follows:
|
||||
|
||||
!!! warning "Tagged items"
|
||||
|
||||
Tagged items will throw a parse error by default. They can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`. They can be stored by passing `cbor_tag_handler_t::store` to function `from_cbor`.
|
||||
Tagged items (0xC0..0xDB) will throw a parse error by default. They can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`, in which case the tag is skipped and the enclosed data item is parsed on its own. They can be stored by passing `cbor_tag_handler_t::store` to function `from_cbor`. Note that no tag is ever interpreted: for instance, a text string tagged with tag 0 (date/time) stays a string.
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -54,6 +54,30 @@ json j = {1.0, "hello", 42};
|
||||
auto t = j.get<std::tuple<double, std::string, int>>(); // {1.0, "hello", 42}
|
||||
```
|
||||
|
||||
!!! warning "Serializing a `std::pair`/`std::tuple` whose every element is a string-keyed pair"
|
||||
|
||||
When *every* element of a `#!cpp std::pair` or `#!cpp std::tuple` is itself a two-element array whose first
|
||||
element is a string (for example `#!cpp std::pair<std::string, int>`), serializing it produces a JSON **object**
|
||||
instead of the expected array:
|
||||
|
||||
```cpp
|
||||
using kv = std::pair<std::string, int>;
|
||||
json j = std::pair<kv, kv>{{"a", 1}, {"b", 2}}; // {"a":1,"b":2}, not [["a",1],["b",2]]
|
||||
```
|
||||
|
||||
This is a consequence of the [brace-initializer object-detection rule](creating_values.md): the same rule that
|
||||
lets `#!cpp json{{"a", 1}, {"b", 2}}` create an object also fires here. The resulting object cannot be read back
|
||||
into the original type (`#!cpp get<std::pair<kv, kv>>()` throws [`type_error.302`](../home/exceptions.md#jsonexceptiontype_error302)),
|
||||
and duplicate keys collapse into one, losing elements. This only affects `#!cpp std::pair`/`#!cpp std::tuple`
|
||||
themselves; a `#!cpp std::vector<std::pair<std::string, int>>`, or a pair/tuple with at least one element that is
|
||||
not a string-keyed pair, serializes to an array as expected. To force an array, build one explicitly from the
|
||||
elements with [`array`](../api/basic_json/array.md):
|
||||
|
||||
```cpp
|
||||
std::pair<kv, kv> p{{"a", 1}, {"b", 2}};
|
||||
json a = json::array({p.first, p.second}); // [["a",1],["b",2]]
|
||||
```
|
||||
|
||||
!!! info "Extracting references into a tuple"
|
||||
|
||||
A tuple type may also hold references (e.g. `#!cpp std::tuple<double&, std::string&>`) to avoid copying: `get`
|
||||
|
||||
@@ -965,3 +965,19 @@ A JSON Patch operation 'test' failed. The unsuccessful operation is also printed
|
||||
```
|
||||
[json.exception.other_error.501] unsuccessful: {"op":"test","path":"/baz","value":"bar"}
|
||||
```
|
||||
|
||||
### json.exception.other_error.502
|
||||
|
||||
[`to_ubjson`](../api/basic_json/to_ubjson.md) and [`to_bjdata`](../api/basic_json/to_bjdata.md) were called with
|
||||
`use_type = true` but `use_size = false`. UBJSON requires a size marker (`#`) after a type marker (`$`).
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
```
|
||||
[json.exception.other_error.502] use_type requires use_size = true
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
This exception was added in version 3.13.0. Before that, debug builds aborted on an assertion and release builds
|
||||
wrote a `$` marker without `#`, which [`from_ubjson`](../api/basic_json/from_ubjson.md) then rejected.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
wheel==0.47.0
|
||||
wheel==0.48.0
|
||||
|
||||
mkdocs==1.6.1 # documentation framework
|
||||
mkdocs-git-revision-date-localized-plugin==1.5.3 # plugin "git-revision-date-localized"
|
||||
|
||||
@@ -773,7 +773,13 @@ class binary_reader
|
||||
case 0xBF: // map (indefinite length)
|
||||
return get_cbor_object(detail::unknown_size(), tag_handler);
|
||||
|
||||
case 0xC6: // tagged item
|
||||
case 0xC0: // tagged item
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -788,6 +794,9 @@ class binary_reader
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8: // tagged item (1 byte follows)
|
||||
case 0xD9: // tagged item (2 bytes follow)
|
||||
case 0xDA: // tagged item (4 bytes follow)
|
||||
|
||||
@@ -813,7 +813,10 @@ class binary_writer
|
||||
bool prefix_required = true;
|
||||
if (use_type && !j.m_data.m_value.array->empty())
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
|
||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
||||
@@ -859,7 +862,10 @@ class binary_writer
|
||||
|
||||
if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character(bjdata_draft3 ? 'B' : 'U');
|
||||
}
|
||||
@@ -911,7 +917,10 @@ class binary_writer
|
||||
bool prefix_required = true;
|
||||
if (use_type && !j.m_data.m_value.object->empty())
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||
const bool same_prefix = std::all_of(j.begin(), j.end(),
|
||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
||||
|
||||
@@ -11395,7 +11395,13 @@ class binary_reader
|
||||
case 0xBF: // map (indefinite length)
|
||||
return get_cbor_object(detail::unknown_size(), tag_handler);
|
||||
|
||||
case 0xC6: // tagged item
|
||||
case 0xC0: // tagged item
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -11410,6 +11416,9 @@ class binary_reader
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8: // tagged item (1 byte follows)
|
||||
case 0xD9: // tagged item (2 bytes follow)
|
||||
case 0xDA: // tagged item (4 bytes follow)
|
||||
@@ -17747,7 +17756,10 @@ class binary_writer
|
||||
bool prefix_required = true;
|
||||
if (use_type && !j.m_data.m_value.array->empty())
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
|
||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
||||
@@ -17793,7 +17805,10 @@ class binary_writer
|
||||
|
||||
if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character(bjdata_draft3 ? 'B' : 'U');
|
||||
}
|
||||
@@ -17845,7 +17860,10 @@ class binary_writer
|
||||
bool prefix_required = true;
|
||||
if (use_type && !j.m_data.m_value.object->empty())
|
||||
{
|
||||
JSON_ASSERT(use_count);
|
||||
if (!use_count)
|
||||
{
|
||||
JSON_THROW(other_error::create(502, "use_type requires use_size = true", &j));
|
||||
}
|
||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||
const bool same_prefix = std::all_of(j.begin(), j.end(),
|
||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
||||
|
||||
@@ -3843,6 +3843,48 @@ TEST_CASE("all BJData first bytes")
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("BJData use_type requires use_size")
|
||||
{
|
||||
SECTION("non-empty object throws other_error.502")
|
||||
{
|
||||
const json j = {{"a", 1}, {"b", 2}};
|
||||
CHECK_THROWS_WITH_AS(json::to_bjdata(j, false, true),
|
||||
"[json.exception.other_error.502] use_type requires use_size = true",
|
||||
json::other_error&);
|
||||
}
|
||||
|
||||
SECTION("non-empty array throws other_error.502")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
CHECK_THROWS_WITH_AS(json::to_bjdata(j, false, true),
|
||||
"[json.exception.other_error.502] use_type requires use_size = true",
|
||||
json::other_error&);
|
||||
}
|
||||
|
||||
SECTION("scalars do not throw with use_type=true, use_count=false")
|
||||
{
|
||||
CHECK_NOTHROW(json::to_bjdata(42, false, true));
|
||||
CHECK_NOTHROW(json::to_bjdata(3.14, false, true));
|
||||
CHECK_NOTHROW(json::to_bjdata("hello", false, true));
|
||||
CHECK_NOTHROW(json::to_bjdata(true, false, true));
|
||||
CHECK_NOTHROW(json::to_bjdata(nullptr, false, true));
|
||||
}
|
||||
|
||||
SECTION("empty containers do not throw with use_type=true, use_count=false")
|
||||
{
|
||||
CHECK_NOTHROW(json::to_bjdata(json::array(), false, true));
|
||||
CHECK_NOTHROW(json::to_bjdata(json::object(), false, true));
|
||||
}
|
||||
|
||||
SECTION("valid combinations on non-empty containers")
|
||||
{
|
||||
const json j = {{"a", 1}, {"b", 2}};
|
||||
CHECK_NOTHROW(json::to_bjdata(j, false, false));
|
||||
CHECK_NOTHROW(json::to_bjdata(j, true, false));
|
||||
CHECK_NOTHROW(json::to_bjdata(j, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("BJData roundtrips" * doctest::skip())
|
||||
{
|
||||
SECTION("input from self-generated BJData files")
|
||||
|
||||
+13
-2
@@ -2565,11 +2565,16 @@ TEST_CASE("Tagged values")
|
||||
const json j = "s";
|
||||
auto v = json::to_cbor(j);
|
||||
|
||||
SECTION("0xC6..0xD4")
|
||||
const json j_bin_payload = json::binary(std::vector<std::uint8_t> {0x01, 0x02, 0x03});
|
||||
auto v_bin_payload = json::to_cbor(j_bin_payload);
|
||||
|
||||
SECTION("0xC0..0xD7")
|
||||
{
|
||||
for (const auto b : std::vector<std::uint8_t>
|
||||
{
|
||||
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
|
||||
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
|
||||
0xD5, 0xD6, 0xD7
|
||||
})
|
||||
{
|
||||
CAPTURE(b);
|
||||
@@ -2589,6 +2594,12 @@ TEST_CASE("Tagged values")
|
||||
|
||||
auto j_tagged_stored = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::store);
|
||||
CHECK(j_tagged_stored == j);
|
||||
|
||||
auto v_binary_tagged = v_bin_payload;
|
||||
v_binary_tagged.insert(v_binary_tagged.begin(), b);
|
||||
auto j_binary_tagged_stored = json::from_cbor(v_binary_tagged, true, true, json::cbor_tag_handler_t::store);
|
||||
CHECK(j_binary_tagged_stored == j_bin_payload);
|
||||
CHECK(!j_binary_tagged_stored.get_binary().has_subtype());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2503,6 +2503,48 @@ TEST_CASE("all UBJSON first bytes")
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("UBJSON use_type requires use_size")
|
||||
{
|
||||
SECTION("non-empty array throws other_error.502")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
CHECK_THROWS_WITH_AS(json::to_ubjson(j, false, true),
|
||||
"[json.exception.other_error.502] use_type requires use_size = true",
|
||||
json::other_error&);
|
||||
}
|
||||
|
||||
SECTION("non-empty object throws other_error.502")
|
||||
{
|
||||
const json j = {{"a", 1}, {"b", 2}};
|
||||
CHECK_THROWS_WITH_AS(json::to_ubjson(j, false, true),
|
||||
"[json.exception.other_error.502] use_type requires use_size = true",
|
||||
json::other_error&);
|
||||
}
|
||||
|
||||
SECTION("scalars do not throw with use_type=true, use_count=false")
|
||||
{
|
||||
CHECK_NOTHROW(json::to_ubjson(42, false, true));
|
||||
CHECK_NOTHROW(json::to_ubjson(3.14, false, true));
|
||||
CHECK_NOTHROW(json::to_ubjson("hello", false, true));
|
||||
CHECK_NOTHROW(json::to_ubjson(true, false, true));
|
||||
CHECK_NOTHROW(json::to_ubjson(nullptr, false, true));
|
||||
}
|
||||
|
||||
SECTION("empty containers do not throw with use_type=true, use_count=false")
|
||||
{
|
||||
CHECK_NOTHROW(json::to_ubjson(json::array(), false, true));
|
||||
CHECK_NOTHROW(json::to_ubjson(json::object(), false, true));
|
||||
}
|
||||
|
||||
SECTION("valid combinations on non-empty containers")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
CHECK_NOTHROW(json::to_ubjson(j, false, false));
|
||||
CHECK_NOTHROW(json::to_ubjson(j, true, false));
|
||||
CHECK_NOTHROW(json::to_ubjson(j, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("UBJSON roundtrips" * doctest::skip())
|
||||
{
|
||||
SECTION("input from self-generated UBJSON files")
|
||||
|
||||
Reference in New Issue
Block a user