Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental support for BSON (de)serialization #1254

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f06c8fd
BSON: serialization of non-objects is not supported
julian-becker Sep 14, 2018
5f5836c
BSON: Support empty objects
julian-becker Sep 14, 2018
9a0dddc
BSON: Object with single boolean
julian-becker Sep 15, 2018
0c0f2e4
BSON: support doubles
julian-becker Sep 15, 2018
6c447de
BSON: Support objects with string members
julian-becker Sep 15, 2018
c5ef023
BSON: support objects with null members
julian-becker Sep 15, 2018
7ee361f
BSON: support objects with int32 members
julian-becker Sep 15, 2018
c0d8921
BSON: support objects with int64 members
julian-becker Sep 15, 2018
83b427a
BSON: unsigned integers
julian-becker Sep 15, 2018
5ce7d6b
BSON: support objects with objects as members
julian-becker Sep 15, 2018
120d1d7
BSON: test case for a more complex document
julian-becker Sep 15, 2018
cf485c2
BSON: Support for arrays
julian-becker Sep 15, 2018
df33a90
BSON: Bugfix for non-empty arrays
julian-becker Sep 15, 2018
763705c
Fix: Add missing `begin()` and `end()` member functions to `alt_string`
julian-becker Sep 24, 2018
bce4816
BSON: Added test case for the different input/output_adapters
julian-becker Sep 24, 2018
ef358ae
BSON: Fixed hangup in case of incomplete bson input and improved test…
julian-becker Sep 25, 2018
0a09db9
BSON: Extend `binary_reader::get_number` to be able to hanlde little …
julian-becker Sep 29, 2018
e8730e5
BSON: Reworked `binary_reader::get_bson_cstr()`
julian-becker Sep 29, 2018
81f4b34
BSON: Improved documentation and error handling/reporting
julian-becker Oct 7, 2018
062aeaf
BSON: Reworked the `binary_writer` such that it precomputes the size …
julian-becker Oct 7, 2018
df0f612
BSON: allow and discard values and object entries of type `value_t::d…
julian-becker Oct 7, 2018
5bccacd
BSON: throw json.exception.out_of_range.407 in case a value of type `…
julian-becker Oct 16, 2018
daa3ca8
BSON: Adjusted documentation of `binary_writer::to_bson()`
julian-becker Oct 16, 2018
978c3c4
BSON: throw `json.exception.out_of_range.409` in case a key to be ser…
julian-becker Oct 16, 2018
2a63869
Merge branch 'develop' of https://github.com/nlohmann/json into featu…
julian-becker Oct 17, 2018
8de10c5
BSON: Hopefully fixing ambiguity (on some compilers) to call to strin…
julian-becker Oct 17, 2018
5ba812d
BSON: fixed incorrect casting in unit-bson.cpp
julian-becker Oct 18, 2018
ad11b6c
BSON: Improved exception-related tests and report location of U+0000 …
julian-becker Oct 18, 2018
24a4142
BSON: Fixed array serialization by adding increasing integral names t…
julian-becker Oct 25, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/nlohmann/detail/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch op
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |

@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
Expand Down
6 changes: 4 additions & 2 deletions include/nlohmann/detail/output/binary_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,11 @@ class binary_writer
*/
static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name)
{
if (name.find(static_cast<typename BasicJsonType::string_t::value_type>(0)) != BasicJsonType::string_t::npos)
const auto it = name.find(static_cast<typename BasicJsonType::string_t::value_type>(0));
if (it != BasicJsonType::string_t::npos)
{
JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000"));
JSON_THROW(out_of_range::create(409,
"BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
}

return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
Expand Down
8 changes: 5 additions & 3 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch op
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |

@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
Expand Down Expand Up @@ -8840,9 +8840,11 @@ class binary_writer
*/
static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name)
{
if (name.find(static_cast<typename BasicJsonType::string_t::value_type>(0)) != BasicJsonType::string_t::npos)
const auto it = name.find(static_cast<typename BasicJsonType::string_t::value_type>(0));
if (it != BasicJsonType::string_t::npos)
{
JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000"));
JSON_THROW(out_of_range::create(409,
"BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
}

return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
Expand Down
31 changes: 22 additions & 9 deletions test/src/unit-bson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,46 +48,53 @@ TEST_CASE("BSON")
SECTION("null")
{
json j = nullptr;
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 0 cannot be serialized to requested format");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "type 0" etc. is a helpful description for users of the library. Please use type_name() to explicitly name the type (null, boolean, etc.).

Furthermore, "to requested format" should be replaced by "BSON" to be explicit.

}

SECTION("boolean")
{
SECTION("true")
{
json j = true;
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 4 cannot be serialized to requested format");
}

SECTION("false")
{
json j = false;
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 4 cannot be serialized to requested format");
}
}

SECTION("number")
{
json j = 42;
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 5 cannot be serialized to requested format");
}

SECTION("float")
{
json j = 4.2;
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 7 cannot be serialized to requested format");
}

SECTION("string")
{
json j = "not supported";
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 3 cannot be serialized to requested format");
}

SECTION("array")
{
json j = std::vector<int> {1, 2, 3, 4, 5, 6, 7};
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error);
REQUIRE_THROWS_AS(json::to_bson(j), json::type_error&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] JSON value of type 2 cannot be serialized to requested format");
}
}

Expand All @@ -97,8 +104,8 @@ TEST_CASE("BSON")
{
{ std::string("en\0try", 6), true }
};
REQUIRE_THROWS_AS(json::to_bson(j), json::out_of_range);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.409] BSON key cannot contain code point U+0000");
REQUIRE_THROWS_AS(json::to_bson(j), json::out_of_range&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.409] BSON key cannot contain code point U+0000 (at byte 2)");
}

SECTION("objects")
Expand Down Expand Up @@ -678,6 +685,7 @@ TEST_CASE("Incomplete BSON INPUT")
'e', 'n', 't' // unexpected EOF
};

CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BSON cstring: unexpected end of input");

Expand All @@ -695,6 +703,7 @@ TEST_CASE("Incomplete BSON INPUT 2")
0x08, // entry: boolean, unexpected EOF
};

CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BSON cstring: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
Expand All @@ -717,6 +726,8 @@ TEST_CASE("Incomplete BSON INPUT 3")
0x10, 0x00, 0x02, 0x00, 0x00, 0x00
// missing input data...
};

CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 28: syntax error while parsing BSON element list: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
Expand All @@ -734,6 +745,7 @@ TEST_CASE("Incomplete BSON INPUT 4")
0x0D, 0x00, // size (incomplete), unexpected EOF
};

CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BSON number: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
Expand All @@ -753,6 +765,7 @@ TEST_CASE("Unsupported BSON input")
0x00 // end marker
};

CHECK_THROWS_AS(json::from_bson(bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(bson),
"[json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF");
CHECK(json::from_bson(bson, true, false).is_discarded());
Expand Down