Trying to use nlohmann/json to parse some CBOR payload:

#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    uint8_t data[] = {0xa2, 0x43, 0x72, 0x65, 0x74, 0x81, 0x0d, 0x47,
                      0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0xf5};

    json jresp = json::from_cbor(data, data + (sizeof data / sizeof data[0]));

    return 0;
}

Fails with this error:

libc++abi.dylib: terminating with uncaught exception of type nlohmann::detail::parse_error: [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x43

I tried other decoders, and those are able to decode that payload.

Python's cbor package is able to decode it:

import cbor
print(cbor.loads(b"\xa2\x43\x72\x65\x74\x81\x0d\x47\x73\x75\x63\x63\x65\x73\x73\xf5"))

{b'ret': [13], b'success': True}

CBOR playground at cbor.me is able to decode it:

16 bytes:

A2                   # map(2)
   43                # bytes(3)
      726574         # "ret"
   81                # array(1)
      0D             # unsigned(13)
   47                # bytes(7)
      73756363657373 # "success"
   F5                # primitive(21)

Diagnostic:

{'ret': [13], 'success': true}

Is there some flag to pass to nlohmann/json to make it decode it?

Tried to pass strict=false in json::from_cbor() to no avail.

1

There are 1 best solutions below

4
On

I don't have experience with CBOR but it doesn't seem to prevent you from using binary strings, integers, etc. as JSON keys.

In your case the input data uses 0x43 to define a 3-byte binary key, instead of the expected 0x63 for a 3-byte string. Something similar for success.

Using {0xa2, 0x63, 0x72, 0x65, 0x74, 0x81, 0x0d, 0x67, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0xf5}; works fine with nlohmann/json.

cbor.me differentiate between binary strings (single quotes) and text strings (double quotes). JSON expects/requires double quotes for strings and JSON keys are defined as strings: https://www.json.org/json-en.html

See also: https://stackoverflow.com/a/4162651/4181011


Edit:

What you have:

JSON CBOR
{'ret': [13], 'success': true} A2 # map(2)
43 # bytes(3)
726574 # "ret"
81 # array(1)
0D # unsigned(13)
47 # bytes(7)
73756363657373 # "success"
F5 # primitive(21)

What you want/need:

JSON CBOR
{"ret": [13], "success": true} A2 # map(2)
63 # text(3)
726574 # "ret"
81 # array(1)
0D # unsigned(13)
67 # text(7)
73756363657373 # "success"
F5 # primitive(21)

Edit 2:

You JSON is not valid. The error message says so. At byte 2 the parser expects a string which in CBOR is introduced by the string length (0x60-0x7B) or indefinite string type (0x7F).

Your CBOR payload does not introduce a string but bytes. That's why it is rejected by the parser. 0x43 is not a valid type/length identifier for strings and JSON requires a string at this point.