diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8dbacb78..4ae0cb2d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -54,7 +54,7 @@ To make changes, you need to edit the following files: ## Please don't -- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means. +- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means. - Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project. - Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension. - We shall not extend the library to **support comments**. There is quite some [controversy](https://www.reddit.com/r/programming/comments/4v6chu/why_json_doesnt_support_comments_douglas_crockford/) around this topic, and there were quite some [issues](https://github.com/nlohmann/json/issues/376) on this. We believe that JSON is fine without comments. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d75a67b4..f2c3af6a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -13,7 +13,7 @@ Read the [Contribution Guidelines](https://github.com/nlohmann/json/blob/develop ## Please don't -- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means. +- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means. - Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project. - Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension. - Please do not open pull requests that address **multiple issues**. diff --git a/.travis.yml b/.travis.yml index 91903e64..4c539510 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,7 +168,15 @@ matrix: - os: linux compiler: gcc - env: COMPILER=g++-4.9 + env: compiler=g++-4.8 + addons: + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.8', 'ninja-build'] + + - os: linux + compiler: gcc + env: compiler=g++-4.9 addons: apt: sources: ['ubuntu-toolchain-r-test'] diff --git a/README.md b/README.md index ebaa961b..c41cb8ea 100644 --- a/README.md +++ b/README.md @@ -227,12 +227,15 @@ json j_string = "this is a string"; std::string cpp_string = j_string; // retrieve the string value (explicit JSON to std::string conversion) auto cpp_string2 = j_string.get(); +// retrieve the string value (alternative explicit JSON to std::string conversion) +std::string cpp_string3; +j_string.get_to(cpp_string3); // retrieve the serialized value (explicit JSON serialization) std::string serialized_string = j_string.dump(); // output of original string -std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get() << '\n'; +std::cout << cpp_string << " == " << cpp_string2 << " == " << cpp_string3 << " == " << j_string.get() << '\n'; // output of serialized value std::cout << j_string << " == " << serialized_string << std::endl; ``` @@ -643,15 +646,15 @@ namespace ns { } void from_json(const json& j, person& p) { - p.name = j.at("name").get(); - p.address = j.at("address").get(); - p.age = j.at("age").get(); + j.at("name").get_to(p.name); + j.at("address").get_to(p.address); + j.at("age").get_to(p.age); } } // namespace ns ``` That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. -Likewise, when calling `get()`, the `from_json` method will be called. +Likewise, when calling `get()` or `get_to(your_type&)`, the `from_json` method will be called. Some important things: @@ -659,9 +662,8 @@ Some important things: * Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use the implicit conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. * When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) * In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. -* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get();` instead. +* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get();` or `your_json.get_to(your_variable);` instead. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. -* Be careful with the definition order of the `from_json`/`to_json` functions: If a type `B` has a member of type `A`, you **MUST** define `to_json(A)` before `to_json(B)`. Look at [issue 561](https://github.com/nlohmann/json/issues/561) for more details. #### How do I convert third-party types? @@ -843,7 +845,7 @@ json j_from_ubjson = json::from_ubjson(v_ubjson); Though it's 2018 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- GCC 4.9 - 8.2 (and possibly later) +- GCC 4.8 - 8.2 (and possibly later) - Clang 3.4 - 6.1 (and possibly later) - Intel C++ Compiler 17.0.2 (and possibly later) - Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) @@ -853,7 +855,7 @@ I would be happy to learn about other compilers/versions. Please note: -- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues. +- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler. - Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default. ``` @@ -872,6 +874,7 @@ The following compilers are currently used in continuous integration at [Travis] | Compiler | Operating System | Version String | |-----------------|------------------------------|----------------| +| GCC 4.8.5 | Ubuntu 14.04.5 LTS | g++-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.2) 4.8.5 | | GCC 4.9.4 | Ubuntu 14.04.1 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 | | GCC 5.5.0 | Ubuntu 14.04.1 LTS | g++-5 (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010 | | GCC 6.4.0 | Ubuntu 14.04.1 LTS | g++-6 (Ubuntu 6.4.0-17ubuntu1~14.04) 6.4.0 20180424 | diff --git a/doc/examples/get_to.cpp b/doc/examples/get_to.cpp new file mode 100644 index 00000000..4705b172 --- /dev/null +++ b/doc/examples/get_to.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create a JSON value with different types + json json_types = + { + {"boolean", true}, + { + "number", { + {"integer", 42}, + {"floating-point", 17.23} + } + }, + {"string", "Hello, world!"}, + {"array", {1, 2, 3, 4, 5}}, + {"null", nullptr} + }; + + bool v1; + int v2; + short v3; + float v4; + int v5; + std::string v6; + std::vector v7; + std::unordered_map v8; + + + // use explicit conversions + json_types["boolean"].get_to(v1); + json_types["number"]["integer"].get_to(v2); + json_types["number"]["integer"].get_to(v3); + json_types["number"]["floating-point"].get_to(v4); + json_types["number"]["floating-point"].get_to(v5); + json_types["string"].get_to(v6); + json_types["array"].get_to(v7); + json_types.get_to(v8); + + // print the conversion results + std::cout << v1 << '\n'; + std::cout << v2 << ' ' << v3 << '\n'; + std::cout << v4 << ' ' << v5 << '\n'; + std::cout << v6 << '\n'; + + for (auto i : v7) + { + std::cout << i << ' '; + } + std::cout << "\n\n"; + + for (auto i : v8) + { + std::cout << i.first << ": " << i.second << '\n'; + } +} diff --git a/doc/examples/get_to.link b/doc/examples/get_to.link new file mode 100644 index 00000000..02a167b0 --- /dev/null +++ b/doc/examples/get_to.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/get_to.output b/doc/examples/get_to.output new file mode 100644 index 00000000..5cd9cd3a --- /dev/null +++ b/doc/examples/get_to.output @@ -0,0 +1,11 @@ +1 +42 42 +17.23 17 +Hello, world! +1 2 3 4 5 + +string: "Hello, world!" +number: {"floating-point":17.23,"integer":42} +null: null +boolean: true +array: [1,2,3,4,5] diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 80fbece7..06805b1a 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -10,7 +10,7 @@ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index de3676ac..e2655f04 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -442,7 +442,7 @@ class serializer return; } - const bool is_negative = (x <= 0) and (x != 0); // see issue #755 + const bool is_negative = not (x >= 0); // see issue #755 std::size_t i = 0; while (x != 0) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index dfd441a7..a9fb87f1 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -2623,6 +2623,52 @@ class basic_json return JSONSerializer::from_json(*this); } + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value. + The value is filled into the input parameter by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType v; + JSONSerializer::from_json(*this, v); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + + @tparam ValueType the input parameter type. + + @return the input parameter, allowing chaining calls. + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get_to} + + @since version 3.3.0 + */ + template::value and + detail::has_from_json::value, + int> = 0> + ValueType & get_to(ValueType& v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + /*! @brief get a pointer value (implicit) @@ -4915,6 +4961,26 @@ class basic_json return {it, res.second}; } + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args&& ... args) + { + iterator result(this); + assert(m_value.array != nullptr); + + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; + + // This could have been written as: + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + + return result; + } + /*! @brief inserts element @@ -4949,9 +5015,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); - return result; + return insert_iterator(pos, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); @@ -5002,9 +5066,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - return result; + return insert_iterator(pos, cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); @@ -5066,12 +5128,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert( - pos.m_it.array_iterator, - first.m_it.array_iterator, - last.m_it.array_iterator); - return result; + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -5113,9 +5170,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end()); - return result; + return insert_iterator(pos, ilist.begin(), ilist.end()); } /*! @@ -7663,19 +7718,6 @@ class basic_json // specialization of std::swap, and std::hash namespace std { -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value and - is_nothrow_move_assignable::value -) -{ - j1.swap(j2); -} /// hash value for JSON objects template<> @@ -7711,6 +7753,20 @@ struct less< ::nlohmann::detail::value_t> } }; +/*! +@brief exchanges the values of two JSON objects + +@since version 1.0.0 +*/ +template<> +inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( + is_nothrow_move_constructible::value and + is_nothrow_move_assignable::value +) +{ + j1.swap(j2); +} + } // namespace std /*! diff --git a/meson.build b/meson.build index c79dcd3e..be36d19f 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,13 @@ -project('nlohmann_json', 'cpp') +project('nlohmann_json', + 'cpp', + version : '3.2.0', + license : 'MIT', +) nlohmann_json_dep = declare_dependency( - include_directories: include_directories('single_include') + include_directories: include_directories('single_include') ) nlohmann_json_multiple_headers = declare_dependency( - include_directories: include_directories('include') + include_directories: include_directories('include') ) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a6405870..c8b0cc9e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -125,7 +125,7 @@ using json = basic_json<>; #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif @@ -10149,7 +10149,7 @@ class serializer return; } - const bool is_negative = (x <= 0) and (x != 0); // see issue #755 + const bool is_negative = not (x >= 0); // see issue #755 std::size_t i = 0; while (x != 0) @@ -13710,6 +13710,52 @@ class basic_json return JSONSerializer::from_json(*this); } + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value. + The value is filled into the input parameter by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType v; + JSONSerializer::from_json(*this, v); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + + @tparam ValueType the input parameter type. + + @return the input parameter, allowing chaining calls. + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get_to} + + @since version 3.3.0 + */ + template::value and + detail::has_from_json::value, + int> = 0> + ValueType & get_to(ValueType& v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + /*! @brief get a pointer value (implicit) @@ -16002,6 +16048,26 @@ class basic_json return {it, res.second}; } + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args&& ... args) + { + iterator result(this); + assert(m_value.array != nullptr); + + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; + + // This could have been written as: + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + + return result; + } + /*! @brief inserts element @@ -16036,9 +16102,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); - return result; + return insert_iterator(pos, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); @@ -16089,9 +16153,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - return result; + return insert_iterator(pos, cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); @@ -16153,12 +16215,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert( - pos.m_it.array_iterator, - first.m_it.array_iterator, - last.m_it.array_iterator); - return result; + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -16200,9 +16257,7 @@ class basic_json } // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end()); - return result; + return insert_iterator(pos, ilist.begin(), ilist.end()); } /*! @@ -18750,19 +18805,6 @@ class basic_json // specialization of std::swap, and std::hash namespace std { -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value and - is_nothrow_move_assignable::value -) -{ - j1.swap(j2); -} /// hash value for JSON objects template<> @@ -18798,6 +18840,20 @@ struct less< ::nlohmann::detail::value_t> } }; +/*! +@brief exchanges the values of two JSON objects + +@since version 1.0.0 +*/ +template<> +inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( + is_nothrow_move_constructible::value and + is_nothrow_move_assignable::value +) +{ + j1.swap(j2); +} + } // namespace std /*! diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index c7c62fe5..fc8c21e9 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -63,7 +63,7 @@ TEST_CASE("JSON patch") // is not an error, because "a" exists, and "b" will be added to // its value. CHECK_NOTHROW(doc1.patch(patch)); - CHECK(doc1.patch(patch) == R"( + auto doc1_ans = R"( { "a": { "foo": 1, @@ -72,7 +72,8 @@ TEST_CASE("JSON patch") } } } - )"_json); + )"_json; + CHECK(doc1.patch(patch) == doc1_ans); // It is an error in this document: json doc2 = R"({ "q": { "bar": 2 } })"_json; diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 69c0cf29..c5478643 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1427,20 +1427,26 @@ TEST_CASE("regression tests") } })"_json; - CHECK_THROWS_AS(model.patch(R"([{"op": "move", - "from": "/one/two/three", - "path": "/a/b/c"}])"_json), json::out_of_range&); - CHECK_THROWS_WITH(model.patch(R"([{"op": "move", - "from": "/one/two/three", - "path": "/a/b/c"}])"_json), + auto p1 = R"([{"op": "move", + "from": "/one/two/three", + "path": "/a/b/c"}])"_json; + CHECK_THROWS_AS(model.patch(p1), json::out_of_range&); + + auto p2 = R"([{"op": "move", + "from": "/one/two/three", + "path": "/a/b/c"}])"_json; + CHECK_THROWS_WITH(model.patch(p2), "[json.exception.out_of_range.403] key 'a' not found"); - CHECK_THROWS_AS(model.patch(R"([{"op": "copy", + auto p3 = R"([{"op": "copy", + "from": "/one/two/three", + "path": "/a/b/c"}])"_json; + CHECK_THROWS_AS(model.patch(p3), json::out_of_range&); + + auto p4 = R"([{"op": "copy", "from": "/one/two/three", - "path": "/a/b/c"}])"_json), json::out_of_range&); - CHECK_THROWS_WITH(model.patch(R"([{"op": "copy", - "from": "/one/two/three", - "path": "/a/b/c"}])"_json), + "path": "/a/b/c"}])"_json; + CHECK_THROWS_WITH(model.patch(p4), "[json.exception.out_of_range.403] key 'a' not found"); } diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 237eb34e..5767ebce 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -405,7 +405,7 @@ TEST_CASE("RFC 7159 examples") SECTION("13 Examples") { { - CHECK_NOTHROW(json(R"( + auto json_contents = R"( { "Image": { "Width": 800, @@ -420,11 +420,13 @@ TEST_CASE("RFC 7159 examples") "IDs": [116, 943, 234, 38793] } } - )")); + )"; + + CHECK_NOTHROW(json(json_contents)); } { - CHECK_NOTHROW(json(R"( + auto json_contents = R"( [ { "precision": "zip", @@ -446,7 +448,8 @@ TEST_CASE("RFC 7159 examples") "Zip": "94085", "Country": "US" } - ])")); + ])"; + CHECK_NOTHROW(json(json_contents)); } CHECK(json::parse("\"Hello world!\"") == json("Hello world!")); @@ -1343,13 +1346,11 @@ TEST_CASE("Big List of Naughty Strings") SECTION("roundtripping") { std::ifstream f("test/data/big-list-of-naughty-strings/blns.json"); + std::string line; - while (not f.eof()) + // read lines one by one, bail out on error or eof + while (getline(f, line)) { - // read line - std::string line; - getline(f, line); - // trim whitespace line = trim(line); diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index a2893056..6e5f88ba 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -298,6 +298,19 @@ TEST_CASE("basic usage", "[udt]") CHECK(book == parsed_book); } + SECTION("via explicit calls to get_to") + { + udt::person person; + udt::name name; + + json person_json = big_json["contacts"][0]["person"]; + CHECK(person_json.get_to(person) == sfinae_addict); + + // correct reference gets returned + person_json["name"].get_to(name).m_val = "new name"; + CHECK(name.m_val == "new name"); + } + SECTION("implicit conversions") { const udt::contact_book parsed_book = big_json;