mirror of
https://github.com/nlohmann/json.git
synced 2026-10-26 07:48:55 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ff56d7c91 | ||
|
|
4b09029f4e | ||
|
|
6e8e7d01df | ||
|
|
077c65872b |
No files matched your search
@@ -74,6 +74,11 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs, for instance
|
||||
an invalid byte, a string that is not valid UTF-8, or an object key that is not a string
|
||||
|
||||
The UTF-8 validity of strings is always checked, independent of
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md), because the end of a BON8 string is determined from
|
||||
its encoding. Duplicate object keys are accepted; the last value wins (see
|
||||
[BON8](../../features/binary_formats/bon8.md)).
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the size of the input.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# BON8
|
||||
|
||||
BON8 (Binary Object Notation 8) is a compact binary serialization format for JSON values. It uses the byte values that
|
||||
BON8 (Binary Object Notation 8) is a compact binary serialization format for JSON values. It uses byte values that
|
||||
cannot begin a UTF-8 character as type markers, so strings are stored as plain UTF-8 without a length prefix: a string
|
||||
ends at the first byte that cannot continue it. Integers from -10 to 39, `true`, `false`, `null`, and the floating-point
|
||||
values -1.0, 0.0, and 1.0 take a single byte, and arrays and objects with up to four elements need no terminator.
|
||||
@@ -12,7 +12,7 @@ values -1.0, 0.0, and 1.0 take a single byte, and arrays and objects with up to
|
||||
|
||||
## Byte layout
|
||||
|
||||
BON8 exploits the fact that some byte values can never start a UTF-8 character. These bytes serve as *type markers*, so strings can be stored as plain UTF-8 without a length prefix: a string ends at the first byte that cannot continue it (often the marker of the next value). Small integers, `true`, `false`, `null`, and a few common floats are a single byte. Arrays and objects are introduced by a marker; those with up to four elements encode their size in the marker and need no terminator, while larger ones are closed by the end marker `0xFE`.
|
||||
BON8 exploits the fact that some byte values can never start a UTF-8 character. These bytes serve as *type markers*, so strings can be stored as plain UTF-8 without a length prefix: a string ends at the first byte that cannot continue it: a marker byte, or a lead byte 0xC2..0xF7 followed by a byte outside 0x80..0xBF. The ending byte is often the marker of the next value. Small integers, `true`, `false`, `null`, and a few common floats are a single byte. Arrays and objects are introduced by a marker; those with up to four elements encode their size in the marker and need no terminator, while larger ones are closed by the end marker `0xFE`.
|
||||
|
||||
Consider the following JSON value (shown formatted for readability):
|
||||
|
||||
@@ -33,7 +33,7 @@ Consider the following JSON value (shown formatted for readability):
|
||||
<div class="byte-layout" markdown="0"><table>
|
||||
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
|
||||
<tr><td><code>{</code></td><td><span class="bl bl-t">8A</span></td><td>object with 4 members</td></tr>
|
||||
<tr><td><code>"id": 300,</code></td><td><span class="bl bl-d">69 64</span> <span class="bl bl-t">C4</span> <span class="bl bl-d">04</span></td><td>key: UTF-8 bytes; the string ends at the next byte, which cannot continue a UTF-8 character; value: 2-byte positive integer (lead byte, then a byte below 0x80)</td></tr>
|
||||
<tr><td><code>"id": 300,</code></td><td><span class="bl bl-d">69 64</span> <span class="bl bl-t">C4</span> <span class="bl bl-d">04</span></td><td>key: UTF-8 bytes; the string ends at 0xC4, because the byte after it (0x04) is not a UTF-8 continuation byte, so 0xC4 starts an integer; value: 2-byte positive integer (lead byte, then a byte below 0x80)</td></tr>
|
||||
<tr><td><code>"name": "json",</code></td><td><span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-l">FF</span> <span class="bl bl-d">6A 73 6F 6E</span> <span class="bl bl-l">FF</span></td><td>key: UTF-8 bytes; 0xFF terminates the string as another string follows; value: UTF-8 bytes; terminated as a string key follows</td></tr>
|
||||
<tr><td><code>"pi": 3.14,</code></td><td><span class="bl bl-d">70 69</span> <span class="bl bl-t">8F</span> <span class="bl bl-d">40 09 1E B8 51 EB 85 1F</span></td><td>key: UTF-8 bytes; value: binary64 (IEEE 754, big-endian); its marker also ends <code>"pi"</code></td></tr>
|
||||
<tr><td><code>"tags": [</code></td><td><span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">82</span></td><td>key: UTF-8 bytes; value: array with 2 elements; its marker also ends <code>"tags"</code></td></tr>
|
||||
@@ -100,7 +100,8 @@ serialized as 0x81 0x65 0xFF, but `[1,2,3,4,"e"]` as 0x85 0x91 0x92 0x93 0x94 0x
|
||||
|
||||
The following values can **not** be converted to a BON8 value:
|
||||
|
||||
- unsigned integers above 9223372036854775807, because BON8 has no unsigned 64-bit integer type
|
||||
- integers outside the int64 range (unsigned integers above 9223372036854775807 and, for number types wider than
|
||||
64 bits, any larger or smaller integer), because BON8 integers are limited to int64
|
||||
([out_of_range.407](../../home/exceptions.md#jsonexceptionout_of_range407))
|
||||
- strings that are not valid UTF-8, because the end of a string is determined from its encoding
|
||||
([type_error.316](../../home/exceptions.md#jsonexceptiontype_error316))
|
||||
@@ -168,7 +169,13 @@ The library maps BON8 types to JSON value types as follows:
|
||||
|
||||
Non-negative integers are read as number_unsigned, negative integers as number_integer.
|
||||
|
||||
!!! info
|
||||
A byte 0xF5..0xF7 followed by 0x80..0xBF is neither a string nor an integer and is rejected with
|
||||
[parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) (invalid UTF-8 byte). The same error is
|
||||
reported for any other invalid byte (such as a stray 0xFE), for ill-formed UTF-8, and for an object key that is not a
|
||||
string. Input that ends prematurely, trailing data after the value, and a missing final 0xFF after a string at the end
|
||||
of the message are reported as [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110).
|
||||
|
||||
!!! info "Non-canonical input"
|
||||
|
||||
Values that do not use the canonical representation, such as integers with a longer encoding than necessary,
|
||||
arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a
|
||||
@@ -176,7 +183,10 @@ Non-negative integers are read as number_unsigned, negative integers as number_i
|
||||
|
||||
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF.
|
||||
|
||||
!!! info
|
||||
Duplicate object keys are accepted; the last value wins (`ordered_json` keeps the position of the first occurrence).
|
||||
The specification does not say how to treat them; the HikoGUI reference decoder keeps the first value.
|
||||
|
||||
!!! info "Round trips"
|
||||
|
||||
Any BON8 output created by `to_bon8` can be successfully parsed by `from_bon8`.
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ array of integers.
|
||||
0x87 // object with 1 member
|
||||
0x62 0x69 0x6E 0x61 0x72 0x79 // "binary"
|
||||
0x84 // array with 4 elements
|
||||
0xC3 0x22 0xC3 0x56 0xC3 0x12 0xC3 0x16 // content (each byte as a 2-byte integer)
|
||||
0xC3 0x22 0xC3 0x56 0xC3 0x12 0xC3 0x16 // content (each byte, here all above 39, as a 2-byte integer)
|
||||
```
|
||||
|
||||
Note that the subtype is lost, and deserializing `v` would yield the following value:
|
||||
|
||||
@@ -346,7 +346,7 @@ been read, or (with `strict = true`) further bytes follow the value.
|
||||
|
||||
### json.exception.parse_error.112
|
||||
|
||||
An unexpected byte was read in a [binary format](../features/binary_formats/index.md) or length information is invalid ([BSON](../features/binary_formats/bson.md)).
|
||||
An unexpected byte was read in a [binary format](../features/binary_formats/index.md) or length information is invalid ([BSON](../features/binary_formats/bson.md)). In [BON8](../features/binary_formats/bon8.md), this exception is also thrown for a key that is not a string and for ill-formed UTF-8.
|
||||
|
||||
!!! failure "Example messages"
|
||||
|
||||
@@ -371,15 +371,21 @@ An unexpected byte was read in a [binary format](../features/binary_formats/inde
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 5: syntax error while parsing BSON document: document size 6 does not match the number of bytes read (5)
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 2: syntax error while parsing BON8 string: invalid UTF-8 byte: 0x80
|
||||
```
|
||||
|
||||
### json.exception.parse_error.113
|
||||
|
||||
A string could not be read from a [binary format](../features/binary_formats/index.md): either a value that is not a
|
||||
string was read where one was required (for instance as a map key), the string's length specification is invalid, or
|
||||
the string's bytes are not valid UTF-8 and the `error_handler` parameter of the corresponding `from_*` function is
|
||||
set to `strict`. By default (`error_handler_t::keep`), the bytes of a string are not checked for valid UTF-8 on read;
|
||||
see the ill-formed UTF-8 notes on the individual [binary format](../features/binary_formats/index.md) pages for how
|
||||
set to `strict`. By default (`error_handler_t::keep`), the bytes of a string are not checked for valid UTF-8 on read.
|
||||
This applies to the `from_*` functions that have an `error_handler` parameter; `from_bon8` does not have one.
|
||||
See the ill-formed UTF-8 notes on the individual [binary format](../features/binary_formats/index.md) pages for how
|
||||
such a string is handled depending on `error_handler`.
|
||||
[`from_bon8()`](../api/basic_json/from_bon8.md) never throws this exception: BON8 non-string keys and ill-formed UTF-8
|
||||
are reported as [parse_error.112](#jsonexceptionparse_error112).
|
||||
|
||||
CBOR and MessagePack allow map keys of any type, but JSON object keys are always strings. Maps with keys of any other
|
||||
type (for instance integers or `null`) are therefore not supported; see the notes on
|
||||
@@ -815,6 +821,9 @@ The binary writers [`to_cbor()`](../api/basic_json/to_cbor.md), [`to_ubjson()`](
|
||||
as well for a string value or object key that is not valid UTF-8 if their `error_handler` is `strict` (the default if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) is enabled). So does
|
||||
[`to_msgpack()`](../api/basic_json/to_msgpack.md) if `error_handler_t::strict` is passed.
|
||||
[`to_bon8()`](../api/basic_json/to_bon8.md) always throws this exception for such a string or key, regardless of
|
||||
[`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md), because the end of a BON8 string is determined
|
||||
from its UTF-8 encoding.
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
@@ -1009,7 +1018,8 @@ double-precision number when `number_float_t` is `#!cpp float`.
|
||||
An integer number cannot be represented by the binary format it is serialized to:
|
||||
|
||||
- [BON8](../features/binary_formats/bon8.md) only stores integers that fit into int64, so
|
||||
[`to_bon8`](../api/basic_json/to_bon8.md) throws for unsigned integers greater than 9223372036854775807.
|
||||
[`to_bon8`](../api/basic_json/to_bon8.md) throws for unsigned integers greater than 9223372036854775807 and, with a
|
||||
number type wider than 64 bits, for any integer outside the int64 range.
|
||||
- [CBOR](../features/binary_formats/cbor.md), [MessagePack](../features/binary_formats/messagepack.md), and
|
||||
[BSON](../features/binary_formats/bson.md) store integers in at most 64 bits. With the default number types, every
|
||||
integer fits, but a [`number_integer_t`](../api/basic_json/number_integer_t.md) or
|
||||
|
||||
Reference in new issue
Block a user