# CBOR The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small code sizes, fairly small message size, and extensibility without the need for version negotiation. !!! abstract "References" - [CBOR Website](http://cbor.io) - the main source on CBOR - [CBOR Playground](http://cbor.me) - an interactive webpage to translate between JSON and CBOR - [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) - the CBOR specification ## Serialization The library uses the following mapping from JSON values types to CBOR types according to the CBOR specification ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html)): | JSON value type | value/range | CBOR type | first byte | |-----------------|--------------------------------------------|-----------------------------------|------------| | null | `null` | Null | 0xF6 | | boolean | `true` | True | 0xF5 | | boolean | `false` | False | 0xF4 | | number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B | | number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A | | number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 | | number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 | | number_integer | -24..-1 | Negative integer | 0x20..0x37 | | number_integer | 0..23 | Integer | 0x00..0x17 | | number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 | | number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 | | number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A | | number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B | | number_unsigned | 0..23 | Integer | 0x00..0x17 | | number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 | | number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 | | number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A | | number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B | | number_float | *any value representable by a float* | Single-Precision Float | 0xFA | | number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB | | string | *length*: 0..23 | UTF-8 string | 0x60..0x77 | | string | *length*: 24..255 | UTF-8 string (1 byte follow) | 0x78 | | string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 | | string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A | | string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B | | array | *size*: 0..23 | array | 0x80..0x97 | | array | *size*: 24..255 | array (1 byte follow) | 0x98 | | array | *size*: 256..65535 | array (2 bytes follow) | 0x99 | | array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A | | array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B | | object | *size*: 0..23 | map | 0xA0..0xB7 | | object | *size*: 24..255 | map (1 byte follow) | 0xB8 | | object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 | | object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA | | object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB | | binary | *size*: 0..23 | byte string | 0x40..0x57 | | binary | *size*: 24..255 | byte string (1 byte follow) | 0x58 | | binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 | | binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A | | binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B | Binary values with subtype are mapped to tagged values (0xD8..0xDB) depending on the subtype, followed by a byte string, see "binary" cells in the table above. !!! success "Complete mapping" The mapping is **complete** in the sense that any JSON value type can be converted to a CBOR value. !!! info "NaN/infinity handling" `NaN`, `Infinity`, and `-Infinity` are serialized as a CBOR half-precision float (type 0xF9, 3 bytes total): `NaN` as `0xF9 0x7E 0x00`, `Infinity` as `0xF9 0x7C 0x00`, and `-Infinity` as `0xF9 0xFC 0x00`. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`. !!! note Prior to version 3.13.0, NaN and Infinity were instead serialized as a CBOR double-precision float (type 0xFB, 9 bytes total), because the check used to select a smaller encoding compared magnitudes with NaN, which is always `false` and caused the intended half-precision path to be skipped. !!! info "Unused CBOR types" The following CBOR types are not used in the conversion: - UTF-8 strings terminated by "break" (0x7F) - arrays terminated by "break" (0x9F) - maps terminated by "break" (0xBF) - byte strings terminated by "break" (0x5F) - date/time (0xC0..0xC1) - bignum (0xC2..0xC3) - decimal fraction (0xC4) - bigfloat (0xC5) - expected conversions (0xD5..0xD7) - simple values (0xE0..0xF3, 0xF8) - undefined (0xF7) - half-precision floats (0xF9) - break (0xFF) !!! info "Tagged items" Binary subtypes will be serialized as tagged items. See [binary values](../binary_values.md#cbor) for an example. ??? example "Example: serialize a JSON value to CBOR" ```cpp --8<-- "examples/to_cbor.cpp" ``` Output: ```c --8<-- "examples/to_cbor.output" ``` ### Byte layout Consider the following JSON value (shown formatted for readability): ```json { "id": 300, "name": "json", "pi": 3.14, "tags": [ "a", "b" ] } ``` `to_cbor` encodes it to 39 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: type/marker length/count/size data.
| JSON | Bytes | Meaning |
|---|---|---|
{ | A4 | map with 4 key/value pairs |
"id": 300, | 62 69 64 19 01 2C | key: text string of length 2, then its UTF-8 bytes; value: unsigned integer, 2 bytes follow (big-endian) |
"name": "json", | 64 6E 61 6D 65 64 6A 73 6F 6E | key: text string of length 4; value: text string of length 4 |
"pi": 3.14, | 62 70 69 FB 40 09 1E B8 51 EB 85 1F | key: text string of length 2; value: double-precision float (IEEE 754, big-endian) |
"tags": [ | 64 74 61 67 73 82 | key: text string of length 4; value: array with 2 elements |
"a", | 61 61 | text string of length 1 |
"b" | 61 62 | text string of length 1 |
] | no end marker: the element count was given up front | |
} | no end marker: the member count was given up front |