Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
548e7e54
Unverified
Commit
548e7e54
authored
Jul 17, 2020
by
Niels Lohmann
Committed by
GitHub
Jul 17, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2273 from nlohmann/issue1968
Add option to ignore CBOR tags
parents
270f1ae4
93cdf059
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
377 additions
and
34 deletions
+377
-34
include/nlohmann/detail/input/binary_reader.hpp
include/nlohmann/detail/input/binary_reader.hpp
+81
-3
include/nlohmann/json.hpp
include/nlohmann/json.hpp
+21
-14
single_include/nlohmann/json.hpp
single_include/nlohmann/json.hpp
+102
-17
test/src/unit-cbor.cpp
test/src/unit-cbor.cpp
+173
-0
No files found.
include/nlohmann/detail/input/binary_reader.hpp
View file @
548e7e54
...
...
@@ -24,6 +24,13 @@ namespace nlohmann
namespace
detail
{
/// how to treat CBOR tags
enum
class
cbor_tag_handler_t
{
error
,
///< throw a parse_error exception in case of a tag
ignore
///< ignore tags
};
/*!
@brief determine system byte order
...
...
@@ -78,13 +85,15 @@ class binary_reader
@param[in] format the binary format to parse
@param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed
@param[in] tag_handler how to treat CBOR tags
@return
*/
JSON_HEDLEY_NON_NULL
(
3
)
bool
sax_parse
(
const
input_format_t
format
,
json_sax_t
*
sax_
,
const
bool
strict
=
true
)
const
bool
strict
=
true
,
const
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
sax
=
sax_
;
bool
result
=
false
;
...
...
@@ -96,7 +105,7 @@ class binary_reader
break
;
case
input_format_t
:
:
cbor
:
result
=
parse_cbor_internal
();
result
=
parse_cbor_internal
(
true
,
tag_handler
);
break
;
case
input_format_t
:
:
msgpack
:
...
...
@@ -386,10 +395,12 @@ class binary_reader
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser
*/
bool
parse_cbor_internal
(
const
bool
get_char
=
true
)
bool
parse_cbor_internal
(
const
bool
get_char
=
true
,
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
switch
(
get_char
?
get
()
:
current
)
{
...
...
@@ -678,6 +689,73 @@ class binary_reader
case
0xBF
:
// map (indefinite length)
return
get_cbor_object
(
std
::
size_t
(
-
1
));
case
0xC6
:
// tagged item
case
0xC7
:
case
0xC8
:
case
0xC9
:
case
0xCA
:
case
0xCB
:
case
0xCC
:
case
0xCD
:
case
0xCE
:
case
0xCF
:
case
0xD0
:
case
0xD1
:
case
0xD2
:
case
0xD3
:
case
0xD4
:
case
0xD8
:
// tagged item (1 bytes follow)
case
0xD9
:
// tagged item (2 bytes follow)
case
0xDA
:
// tagged item (4 bytes follow)
case
0xDB
:
// tagged item (8 bytes follow)
{
switch
(
tag_handler
)
{
case
cbor_tag_handler_t
:
:
error
:
{
auto
last_token
=
get_token_string
();
return
sax
->
parse_error
(
chars_read
,
last_token
,
parse_error
::
create
(
112
,
chars_read
,
exception_message
(
input_format_t
::
cbor
,
"invalid byte: 0x"
+
last_token
,
"value"
)));
}
case
cbor_tag_handler_t
:
:
ignore
:
{
switch
(
current
)
{
case
0xD8
:
{
std
::
uint8_t
len
{};
get_number
(
input_format_t
::
cbor
,
len
);
break
;
}
case
0xD9
:
{
std
::
uint16_t
len
{};
get_number
(
input_format_t
::
cbor
,
len
);
break
;
}
case
0xDA
:
{
std
::
uint32_t
len
{};
get_number
(
input_format_t
::
cbor
,
len
);
break
;
}
case
0xDB
:
{
std
::
uint64_t
len
{};
get_number
(
input_format_t
::
cbor
,
len
);
break
;
}
default:
break
;
}
return
parse_cbor_internal
(
true
,
tag_handler
);
}
default:
// LCOV_EXCL_LINE
JSON_ASSERT
(
false
);
// LCOV_EXCL_LINE
}
}
case
0xF4
:
// false
return
sax
->
boolean
(
false
);
...
...
include/nlohmann/json.hpp
View file @
548e7e54
...
...
@@ -230,6 +230,8 @@ class basic_json
using
json_serializer
=
JSONSerializer
<
T
,
SFINAE
>
;
/// how to treat decoding errors
using
error_handler_t
=
detail
::
error_handler_t
;
/// how to treat CBOR tags
using
cbor_tag_handler_t
=
detail
::
cbor_tag_handler_t
;
/// helper type for initializer lists of basic_json values
using
initializer_list_t
=
std
::
initializer_list
<
detail
::
json_ref
<
basic_json
>>
;
...
...
@@ -7049,7 +7051,7 @@ class basic_json
vector in CBOR format.,to_cbor}
@sa http://cbor.io
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool
, const cbor_tag_handler_t
) for the
analogous deserialization
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
...
...
@@ -7437,6 +7439,7 @@ class basic_json
(true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default)
@param[in] tag_handler how to treat CBOR tags (optional, error by default)
@return deserialized JSON value; in case of a parse error and
@a allow_exceptions set to `false`, the return value will be
...
...
@@ -7463,34 +7466,36 @@ class basic_json
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
since 3.2.0
since 3.2.0
; added @a tag_handler parameter since 3.9.0.
*/
template
<
typename
InputType
>
JSON_HEDLEY_WARN_UNUSED_RESULT
static
basic_json
from_cbor
(
InputType
&&
i
,
const
bool
strict
=
true
,
const
bool
allow_exceptions
=
true
)
const
bool
allow_exceptions
=
true
,
const
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
basic_json
result
;
detail
::
json_sax_dom_parser
<
basic_json
>
sdp
(
result
,
allow_exceptions
);
auto
ia
=
detail
::
input_adapter
(
std
::
forward
<
InputType
>
(
i
));
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
);
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
,
tag_handler
);
return
res
?
result
:
basic_json
(
value_t
::
discarded
);
}
/*!
@copydoc from_cbor(detail::input_adapter&&, const bool, const bool)
@copydoc from_cbor(detail::input_adapter&&, const bool, const bool
, const cbor_tag_handler_t
)
*/
template
<
typename
IteratorType
>
JSON_HEDLEY_WARN_UNUSED_RESULT
static
basic_json
from_cbor
(
IteratorType
first
,
IteratorType
last
,
const
bool
strict
=
true
,
const
bool
allow_exceptions
=
true
)
const
bool
allow_exceptions
=
true
,
const
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
basic_json
result
;
detail
::
json_sax_dom_parser
<
basic_json
>
sdp
(
result
,
allow_exceptions
);
auto
ia
=
detail
::
input_adapter
(
std
::
move
(
first
),
std
::
move
(
last
));
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
);
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
,
tag_handler
);
return
res
?
result
:
basic_json
(
value_t
::
discarded
);
}
...
...
@@ -7499,9 +7504,10 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR
(
3.8.0
,
from_cbor
(
ptr
,
ptr
+
len
))
static
basic_json
from_cbor
(
const
T
*
ptr
,
std
::
size_t
len
,
const
bool
strict
=
true
,
const
bool
allow_exceptions
=
true
)
const
bool
allow_exceptions
=
true
,
const
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
return
from_cbor
(
ptr
,
ptr
+
len
,
strict
,
allow_exceptions
);
return
from_cbor
(
ptr
,
ptr
+
len
,
strict
,
tag_handler
);
}
...
...
@@ -7509,12 +7515,13 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR
(
3.8.0
,
from_cbor
(
ptr
,
ptr
+
len
))
static
basic_json
from_cbor
(
detail
::
span_input_adapter
&&
i
,
const
bool
strict
=
true
,
const
bool
allow_exceptions
=
true
)
const
bool
allow_exceptions
=
true
,
const
cbor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
error
)
{
basic_json
result
;
detail
::
json_sax_dom_parser
<
basic_json
>
sdp
(
result
,
allow_exceptions
);
auto
ia
=
i
.
get
();
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
);
const
bool
res
=
binary_reader
<
decltype
(
ia
)
>
(
std
::
move
(
ia
)).
sax_parse
(
input_format_t
::
cbor
,
&
sdp
,
strict
,
tag_handler
);
return
res
?
result
:
basic_json
(
value_t
::
discarded
);
}
...
...
@@ -7592,7 +7599,7 @@ class basic_json
@sa http://msgpack.org
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool
, const cbor_tag_handler_t
) for the
related CBOR format
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
the related UBJSON format
...
...
@@ -7710,7 +7717,7 @@ class basic_json
@sa http://ubjson.org
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool
, const cbor_tag_handler_t
) for the
related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format
...
...
@@ -7825,7 +7832,7 @@ class basic_json
@sa http://bsonspec.org/spec.html
@sa @ref to_bson(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool
, const cbor_tag_handler_t
) for the
related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format
...
...
single_include/nlohmann/json.hpp
View file @
548e7e54
This diff is collapsed.
Click to expand it.
test/src/unit-cbor.cpp
View file @
548e7e54
...
...
@@ -2548,3 +2548,176 @@ TEST_CASE("examples from RFC 7049 Appendix A")
CHECK
(
json
::
parse
(
"{
\"
Fun
\"
: true,
\"
Amt
\"
: -2}"
)
==
json
::
from_cbor
(
std
::
vector
<
uint8_t
>
({
0xbf
,
0x63
,
0x46
,
0x75
,
0x6e
,
0xf5
,
0x63
,
0x41
,
0x6d
,
0x74
,
0x21
,
0xff
})));
}
}
TEST_CASE
(
"Tagged values"
)
{
json
j
=
"s"
;
auto
v
=
json
::
to_cbor
(
j
);
SECTION
(
"0xC6..0xD4"
)
{
for
(
std
::
uint8_t
b
:
{
0xC6
,
0xC7
,
0xC8
,
0xC9
,
0xCA
,
0xCB
,
0xCC
,
0xCD
,
0xCE
,
0xCF
,
0xD0
,
0xD1
,
0xD2
,
0xD3
,
0xD4
})
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
b
);
// check that parsing fails in error mode
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
// check that parsing succeeds and gets original value in ignore mode
auto
j_tagged
=
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
);
CHECK
(
j_tagged
==
j
);
}
}
SECTION
(
"0xD8 - 1 byte follows"
)
{
SECTION
(
"success"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xD8
);
// tag
// check that parsing fails in error mode
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
// check that parsing succeeds and gets original value in ignore mode
auto
j_tagged
=
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
);
CHECK
(
j_tagged
==
j
);
}
SECTION
(
"missing byte after tag"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xD8
);
// tag
// check that parsing fails in all modes
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
),
json
::
parse_error
);
}
}
SECTION
(
"0xD9 - 2 byte follow"
)
{
SECTION
(
"success"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xD9
);
// tag
// check that parsing fails in error mode
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
// check that parsing succeeds and gets original value in ignore mode
auto
j_tagged
=
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
);
CHECK
(
j_tagged
==
j
);
}
SECTION
(
"missing byte after tag"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xD9
);
// tag
// check that parsing fails in all modes
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
),
json
::
parse_error
);
}
}
SECTION
(
"0xDA - 4 bytes follow"
)
{
SECTION
(
"success"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xDA
);
// tag
// check that parsing fails in error mode
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
// check that parsing succeeds and gets original value in ignore mode
auto
j_tagged
=
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
);
CHECK
(
j_tagged
==
j
);
}
SECTION
(
"missing bytes after tag"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xDA
);
// tag
// check that parsing fails in all modes
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
),
json
::
parse_error
);
}
}
SECTION
(
"0xDB - 8 bytes follow"
)
{
SECTION
(
"success"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xDB
);
// tag
// check that parsing fails in error mode
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
// check that parsing succeeds and gets original value in ignore mode
auto
j_tagged
=
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
);
CHECK
(
j_tagged
==
j
);
}
SECTION
(
"missing byte after tag"
)
{
// add tag to value
auto
v_tagged
=
v
;
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x42
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x23
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x22
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0x11
);
// 1 byte
v_tagged
.
insert
(
v_tagged
.
begin
(),
0xDB
);
// tag
// check that parsing fails in all modes
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
error
),
json
::
parse_error
);
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
),
json
::
parse_error
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment