Merge branch 'develop' into fix/1237
This commit is contained in:
commit
1fae82b7a7
16 changed files with 317 additions and 97 deletions
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
@ -54,7 +54,7 @@ To make changes, you need to edit the following files:
|
||||||
|
|
||||||
## Please don't
|
## 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.
|
- 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 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.
|
- 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.
|
||||||
|
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -13,7 +13,7 @@ Read the [Contribution Guidelines](https://github.com/nlohmann/json/blob/develop
|
||||||
|
|
||||||
## Please don't
|
## 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.
|
- 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 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**.
|
- Please do not open pull requests that address **multiple issues**.
|
||||||
|
|
10
.travis.yml
10
.travis.yml
|
@ -168,7 +168,15 @@ matrix:
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
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:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
|
21
README.md
21
README.md
|
@ -227,12 +227,15 @@ json j_string = "this is a string";
|
||||||
std::string cpp_string = j_string;
|
std::string cpp_string = j_string;
|
||||||
// retrieve the string value (explicit JSON to std::string conversion)
|
// retrieve the string value (explicit JSON to std::string conversion)
|
||||||
auto cpp_string2 = j_string.get<std::string>();
|
auto cpp_string2 = j_string.get<std::string>();
|
||||||
|
// 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)
|
// retrieve the serialized value (explicit JSON serialization)
|
||||||
std::string serialized_string = j_string.dump();
|
std::string serialized_string = j_string.dump();
|
||||||
|
|
||||||
// output of original string
|
// output of original string
|
||||||
std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
|
std::cout << cpp_string << " == " << cpp_string2 << " == " << cpp_string3 << " == " << j_string.get<std::string>() << '\n';
|
||||||
// output of serialized value
|
// output of serialized value
|
||||||
std::cout << j_string << " == " << serialized_string << std::endl;
|
std::cout << j_string << " == " << serialized_string << std::endl;
|
||||||
```
|
```
|
||||||
|
@ -643,15 +646,15 @@ namespace ns {
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_json(const json& j, person& p) {
|
void from_json(const json& j, person& p) {
|
||||||
p.name = j.at("name").get<std::string>();
|
j.at("name").get_to(p.name);
|
||||||
p.address = j.at("address").get<std::string>();
|
j.at("address").get_to(p.address);
|
||||||
p.age = j.at("age").get<int>();
|
j.at("age").get_to(p.age);
|
||||||
}
|
}
|
||||||
} // namespace ns
|
} // namespace ns
|
||||||
```
|
```
|
||||||
|
|
||||||
That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
|
That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
|
||||||
Likewise, when calling `get<your_type>()`, the `from_json` method will be called.
|
Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_json` method will be called.
|
||||||
|
|
||||||
Some important things:
|
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.
|
* 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>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
|
* When using `get<your_type>()`, `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 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<decltype your_variable>();` 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<decltype(your_variable)>();` 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.
|
* 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?
|
#### 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:
|
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)
|
- Clang 3.4 - 6.1 (and possibly later)
|
||||||
- Intel C++ Compiler 17.0.2 (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)
|
- 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:
|
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.
|
- 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 |
|
| 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 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 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 |
|
| GCC 6.4.0 | Ubuntu 14.04.1 LTS | g++-6 (Ubuntu 6.4.0-17ubuntu1~14.04) 6.4.0 20180424 |
|
||||||
|
|
60
doc/examples/get_to.cpp
Normal file
60
doc/examples/get_to.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
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<short> v7;
|
||||||
|
std::unordered_map<std::string, json> 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';
|
||||||
|
}
|
||||||
|
}
|
1
doc/examples/get_to.link
Normal file
1
doc/examples/get_to.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="https://wandbox.org/permlink/QxtxaO6JZAMJPutC"><b>online</b></a>
|
11
doc/examples/get_to.output
Normal file
11
doc/examples/get_to.output
Normal file
|
@ -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]
|
|
@ -10,7 +10,7 @@
|
||||||
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
|
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
|
#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"
|
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -442,7 +442,7 @@ class serializer
|
||||||
return;
|
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;
|
std::size_t i = 0;
|
||||||
|
|
||||||
while (x != 0)
|
while (x != 0)
|
||||||
|
|
|
@ -2623,6 +2623,52 @@ class basic_json
|
||||||
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
return JSONSerializer<ValueTypeCV>::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<ValueType>
|
||||||
|
`from_json()` method.
|
||||||
|
|
||||||
|
The function is equivalent to executing
|
||||||
|
@code {.cpp}
|
||||||
|
ValueType v;
|
||||||
|
JSONSerializer<ValueType>::from_json(*this, v);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
This overloads is chosen if:
|
||||||
|
- @a ValueType is not @ref basic_json,
|
||||||
|
- @ref json_serializer<ValueType> 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<ValueType> `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<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
associative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,get_to}
|
||||||
|
|
||||||
|
@since version 3.3.0
|
||||||
|
*/
|
||||||
|
template<typename ValueType,
|
||||||
|
detail::enable_if_t <
|
||||||
|
not detail::is_basic_json<ValueType>::value and
|
||||||
|
detail::has_from_json<basic_json_t, ValueType>::value,
|
||||||
|
int> = 0>
|
||||||
|
ValueType & get_to(ValueType& v) const noexcept(noexcept(
|
||||||
|
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
|
||||||
|
{
|
||||||
|
JSONSerializer<ValueType>::from_json(*this, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a pointer value (implicit)
|
@brief get a pointer value (implicit)
|
||||||
|
|
||||||
|
@ -4915,6 +4961,26 @@ class basic_json
|
||||||
return {it, res.second};
|
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<typename... Args>
|
||||||
|
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>(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
|
@brief inserts element
|
||||||
|
|
||||||
|
@ -4949,9 +5015,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, val);
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
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
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, cnt, val);
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
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
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -5113,9 +5170,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, ilist.begin(), ilist.end());
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -7663,19 +7718,6 @@ class basic_json
|
||||||
// specialization of std::swap, and std::hash
|
// specialization of std::swap, and std::hash
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
/*!
|
|
||||||
@brief exchanges the values of two JSON objects
|
|
||||||
|
|
||||||
@since version 1.0.0
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
|
|
||||||
is_nothrow_move_constructible<nlohmann::json>::value and
|
|
||||||
is_nothrow_move_assignable<nlohmann::json>::value
|
|
||||||
)
|
|
||||||
{
|
|
||||||
j1.swap(j2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// hash value for JSON objects
|
/// hash value for JSON objects
|
||||||
template<>
|
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>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
|
||||||
|
is_nothrow_move_constructible<nlohmann::json>::value and
|
||||||
|
is_nothrow_move_assignable<nlohmann::json>::value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
j1.swap(j2);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
10
meson.build
10
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(
|
nlohmann_json_dep = declare_dependency(
|
||||||
include_directories: include_directories('single_include')
|
include_directories: include_directories('single_include')
|
||||||
)
|
)
|
||||||
|
|
||||||
nlohmann_json_multiple_headers = declare_dependency(
|
nlohmann_json_multiple_headers = declare_dependency(
|
||||||
include_directories: include_directories('include')
|
include_directories: include_directories('include')
|
||||||
)
|
)
|
||||||
|
|
|
@ -125,7 +125,7 @@ using json = basic_json<>;
|
||||||
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
|
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
|
#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"
|
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -10149,7 +10149,7 @@ class serializer
|
||||||
return;
|
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;
|
std::size_t i = 0;
|
||||||
|
|
||||||
while (x != 0)
|
while (x != 0)
|
||||||
|
@ -13710,6 +13710,52 @@ class basic_json
|
||||||
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
return JSONSerializer<ValueTypeCV>::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<ValueType>
|
||||||
|
`from_json()` method.
|
||||||
|
|
||||||
|
The function is equivalent to executing
|
||||||
|
@code {.cpp}
|
||||||
|
ValueType v;
|
||||||
|
JSONSerializer<ValueType>::from_json(*this, v);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
This overloads is chosen if:
|
||||||
|
- @a ValueType is not @ref basic_json,
|
||||||
|
- @ref json_serializer<ValueType> 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<ValueType> `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<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
associative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,get_to}
|
||||||
|
|
||||||
|
@since version 3.3.0
|
||||||
|
*/
|
||||||
|
template<typename ValueType,
|
||||||
|
detail::enable_if_t <
|
||||||
|
not detail::is_basic_json<ValueType>::value and
|
||||||
|
detail::has_from_json<basic_json_t, ValueType>::value,
|
||||||
|
int> = 0>
|
||||||
|
ValueType & get_to(ValueType& v) const noexcept(noexcept(
|
||||||
|
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
|
||||||
|
{
|
||||||
|
JSONSerializer<ValueType>::from_json(*this, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a pointer value (implicit)
|
@brief get a pointer value (implicit)
|
||||||
|
|
||||||
|
@ -16002,6 +16048,26 @@ class basic_json
|
||||||
return {it, res.second};
|
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<typename... Args>
|
||||||
|
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>(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
|
@brief inserts element
|
||||||
|
|
||||||
|
@ -16036,9 +16102,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, val);
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
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
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, cnt, val);
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
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
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -16200,9 +16257,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
return insert_iterator(pos, ilist.begin(), ilist.end());
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -18750,19 +18805,6 @@ class basic_json
|
||||||
// specialization of std::swap, and std::hash
|
// specialization of std::swap, and std::hash
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
/*!
|
|
||||||
@brief exchanges the values of two JSON objects
|
|
||||||
|
|
||||||
@since version 1.0.0
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
|
|
||||||
is_nothrow_move_constructible<nlohmann::json>::value and
|
|
||||||
is_nothrow_move_assignable<nlohmann::json>::value
|
|
||||||
)
|
|
||||||
{
|
|
||||||
j1.swap(j2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// hash value for JSON objects
|
/// hash value for JSON objects
|
||||||
template<>
|
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>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
|
||||||
|
is_nothrow_move_constructible<nlohmann::json>::value and
|
||||||
|
is_nothrow_move_assignable<nlohmann::json>::value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
j1.swap(j2);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -63,7 +63,7 @@ TEST_CASE("JSON patch")
|
||||||
// is not an error, because "a" exists, and "b" will be added to
|
// is not an error, because "a" exists, and "b" will be added to
|
||||||
// its value.
|
// its value.
|
||||||
CHECK_NOTHROW(doc1.patch(patch));
|
CHECK_NOTHROW(doc1.patch(patch));
|
||||||
CHECK(doc1.patch(patch) == R"(
|
auto doc1_ans = R"(
|
||||||
{
|
{
|
||||||
"a": {
|
"a": {
|
||||||
"foo": 1,
|
"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:
|
// It is an error in this document:
|
||||||
json doc2 = R"({ "q": { "bar": 2 } })"_json;
|
json doc2 = R"({ "q": { "bar": 2 } })"_json;
|
||||||
|
|
|
@ -1427,20 +1427,26 @@ TEST_CASE("regression tests")
|
||||||
}
|
}
|
||||||
})"_json;
|
})"_json;
|
||||||
|
|
||||||
CHECK_THROWS_AS(model.patch(R"([{"op": "move",
|
auto p1 = R"([{"op": "move",
|
||||||
"from": "/one/two/three",
|
"from": "/one/two/three",
|
||||||
"path": "/a/b/c"}])"_json), json::out_of_range&);
|
"path": "/a/b/c"}])"_json;
|
||||||
CHECK_THROWS_WITH(model.patch(R"([{"op": "move",
|
CHECK_THROWS_AS(model.patch(p1), json::out_of_range&);
|
||||||
"from": "/one/two/three",
|
|
||||||
"path": "/a/b/c"}])"_json),
|
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");
|
"[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",
|
"from": "/one/two/three",
|
||||||
"path": "/a/b/c"}])"_json), json::out_of_range&);
|
"path": "/a/b/c"}])"_json;
|
||||||
CHECK_THROWS_WITH(model.patch(R"([{"op": "copy",
|
CHECK_THROWS_WITH(model.patch(p4),
|
||||||
"from": "/one/two/three",
|
|
||||||
"path": "/a/b/c"}])"_json),
|
|
||||||
"[json.exception.out_of_range.403] key 'a' not found");
|
"[json.exception.out_of_range.403] key 'a' not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -405,7 +405,7 @@ TEST_CASE("RFC 7159 examples")
|
||||||
SECTION("13 Examples")
|
SECTION("13 Examples")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
CHECK_NOTHROW(json(R"(
|
auto json_contents = R"(
|
||||||
{
|
{
|
||||||
"Image": {
|
"Image": {
|
||||||
"Width": 800,
|
"Width": 800,
|
||||||
|
@ -420,11 +420,13 @@ TEST_CASE("RFC 7159 examples")
|
||||||
"IDs": [116, 943, 234, 38793]
|
"IDs": [116, 943, 234, 38793]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)"));
|
)";
|
||||||
|
|
||||||
|
CHECK_NOTHROW(json(json_contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CHECK_NOTHROW(json(R"(
|
auto json_contents = R"(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"precision": "zip",
|
"precision": "zip",
|
||||||
|
@ -446,7 +448,8 @@ TEST_CASE("RFC 7159 examples")
|
||||||
"Zip": "94085",
|
"Zip": "94085",
|
||||||
"Country": "US"
|
"Country": "US"
|
||||||
}
|
}
|
||||||
])"));
|
])";
|
||||||
|
CHECK_NOTHROW(json(json_contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK(json::parse("\"Hello world!\"") == json("Hello world!"));
|
CHECK(json::parse("\"Hello world!\"") == json("Hello world!"));
|
||||||
|
@ -1343,13 +1346,11 @@ TEST_CASE("Big List of Naughty Strings")
|
||||||
SECTION("roundtripping")
|
SECTION("roundtripping")
|
||||||
{
|
{
|
||||||
std::ifstream f("test/data/big-list-of-naughty-strings/blns.json");
|
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
|
// trim whitespace
|
||||||
line = trim(line);
|
line = trim(line);
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,19 @@ TEST_CASE("basic usage", "[udt]")
|
||||||
CHECK(book == parsed_book);
|
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")
|
SECTION("implicit conversions")
|
||||||
{
|
{
|
||||||
const udt::contact_book parsed_book = big_json;
|
const udt::contact_book parsed_book = big_json;
|
||||||
|
|
Loading…
Reference in a new issue