Merge branch 'feature/issue323' into develop
This commit is contained in:
commit
e7a60d8961
7 changed files with 95 additions and 9 deletions
12
README.md
12
README.md
|
@ -515,17 +515,17 @@ To compile and run the tests, you need to execute
|
||||||
$ make check
|
$ make check
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
All tests passed (8905161 assertions in 35 test cases)
|
All tests passed (8905166 assertions in 35 test cases)
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can use [https://cmake.org](CMake) and run
|
Alternatively, you can use [https://cmake.org](CMake) and run
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir build
|
$ mkdir build
|
||||||
cd build
|
$ cd build
|
||||||
cmake ..
|
$ cmake ..
|
||||||
make
|
$ make
|
||||||
ctest
|
$ ctest
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||||
|
|
|
@ -40,7 +40,7 @@ int main()
|
||||||
// output the changed array
|
// output the changed array
|
||||||
std::cout << j["array"] << '\n';
|
std::cout << j["array"] << '\n';
|
||||||
|
|
||||||
// "change" the arry element past the end
|
// "change" the array element past the end
|
||||||
j["/array/-"_json_pointer] = 55;
|
j["/array/-"_json_pointer] = 55;
|
||||||
// output the changed array
|
// output the changed array
|
||||||
std::cout << j["array"] << '\n';
|
std::cout << j["array"] << '\n';
|
||||||
|
|
31
src/json.hpp
31
src/json.hpp
|
@ -32,6 +32,7 @@ SOFTWARE.
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cctype>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
@ -9436,6 +9437,12 @@ basic_json_parser_63:
|
||||||
/*!
|
/*!
|
||||||
@brief return a reference to the pointed to value
|
@brief return a reference to the pointed to value
|
||||||
|
|
||||||
|
@note This version does not throw if a value is not present, but tries
|
||||||
|
to create nested values instead. For instance, calling this function
|
||||||
|
with pointer `"/this/that"` on a null value is equivalent to calling
|
||||||
|
`operator[]("this").operator[]("that")` on that value, effectively
|
||||||
|
changing the null value to an object.
|
||||||
|
|
||||||
@param[in] ptr a JSON value
|
@param[in] ptr a JSON value
|
||||||
|
|
||||||
@return reference to the JSON value pointed to by the JSON pointer
|
@return reference to the JSON value pointed to by the JSON pointer
|
||||||
|
@ -9450,6 +9457,29 @@ basic_json_parser_63:
|
||||||
{
|
{
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
|
// convert null values to arrays or objects before continuing
|
||||||
|
if (ptr->m_type == value_t::null)
|
||||||
|
{
|
||||||
|
// check if reference token is a number
|
||||||
|
const bool nums = std::all_of(reference_token.begin(),
|
||||||
|
reference_token.end(),
|
||||||
|
[](const char x)
|
||||||
|
{
|
||||||
|
return std::isdigit(x);
|
||||||
|
});
|
||||||
|
|
||||||
|
// change value to array for numbers or "-" or to object
|
||||||
|
// otherwise
|
||||||
|
if (nums or reference_token == "-")
|
||||||
|
{
|
||||||
|
*ptr = value_t::array;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr = value_t::object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (ptr->m_type)
|
switch (ptr->m_type)
|
||||||
{
|
{
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
|
@ -9461,6 +9491,7 @@ basic_json_parser_63:
|
||||||
|
|
||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
|
|
||||||
// error condition (cf. RFC 6901, Sect. 4)
|
// error condition (cf. RFC 6901, Sect. 4)
|
||||||
if (reference_token.size() > 1 and reference_token[0] == '0')
|
if (reference_token.size() > 1 and reference_token[0] == '0')
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ SOFTWARE.
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cctype>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
@ -8733,6 +8734,12 @@ class basic_json
|
||||||
/*!
|
/*!
|
||||||
@brief return a reference to the pointed to value
|
@brief return a reference to the pointed to value
|
||||||
|
|
||||||
|
@note This version does not throw if a value is not present, but tries
|
||||||
|
to create nested values instead. For instance, calling this function
|
||||||
|
with pointer `"/this/that"` on a null value is equivalent to calling
|
||||||
|
`operator[]("this").operator[]("that")` on that value, effectively
|
||||||
|
changing the null value to an object.
|
||||||
|
|
||||||
@param[in] ptr a JSON value
|
@param[in] ptr a JSON value
|
||||||
|
|
||||||
@return reference to the JSON value pointed to by the JSON pointer
|
@return reference to the JSON value pointed to by the JSON pointer
|
||||||
|
@ -8747,6 +8754,29 @@ class basic_json
|
||||||
{
|
{
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
|
// convert null values to arrays or objects before continuing
|
||||||
|
if (ptr->m_type == value_t::null)
|
||||||
|
{
|
||||||
|
// check if reference token is a number
|
||||||
|
const bool nums = std::all_of(reference_token.begin(),
|
||||||
|
reference_token.end(),
|
||||||
|
[](const char x)
|
||||||
|
{
|
||||||
|
return std::isdigit(x);
|
||||||
|
});
|
||||||
|
|
||||||
|
// change value to array for numbers or "-" or to object
|
||||||
|
// otherwise
|
||||||
|
if (nums or reference_token == "-")
|
||||||
|
{
|
||||||
|
*ptr = value_t::array;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr = value_t::object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (ptr->m_type)
|
switch (ptr->m_type)
|
||||||
{
|
{
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
|
@ -8758,6 +8788,7 @@ class basic_json
|
||||||
|
|
||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
|
|
||||||
// error condition (cf. RFC 6901, Sect. 4)
|
// error condition (cf. RFC 6901, Sect. 4)
|
||||||
if (reference_token.size() > 1 and reference_token[0] == '0')
|
if (reference_token.size() > 1 and reference_token[0] == '0')
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,6 +238,18 @@ TEST_CASE("deserialization")
|
||||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("case 3")
|
||||||
|
{
|
||||||
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
|
||||||
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("case 4")
|
||||||
|
{
|
||||||
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
|
||||||
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,8 +109,13 @@ TEST_CASE("JSON pointers")
|
||||||
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
||||||
|
|
||||||
// unescaped access
|
// unescaped access
|
||||||
CHECK_THROWS_AS(j[json::json_pointer("/a/b")], std::out_of_range);
|
// access to nonexisting values yield object creation
|
||||||
CHECK_THROWS_WITH(j[json::json_pointer("/a/b")], "unresolved reference token 'b'");
|
CHECK_NOTHROW(j[json::json_pointer("/a/b")] = 42);
|
||||||
|
CHECK(j["a"]["b"] == json(42));
|
||||||
|
CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
|
||||||
|
CHECK(j["a"]["c"] == json({nullptr, 42}));
|
||||||
|
CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
|
||||||
|
CHECK(j["a"]["d"] == json::array({42}));
|
||||||
// "/a/b" works for JSON {"a": {"b": 42}}
|
// "/a/b" works for JSON {"a": {"b": 42}}
|
||||||
CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
|
CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
|
||||||
|
|
||||||
|
|
|
@ -482,4 +482,11 @@ TEST_CASE("regression tests")
|
||||||
CHECK_NOTHROW(j << f);
|
CHECK_NOTHROW(j << f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("issue #323 - add nested object capabilities to pointers")
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["/this/that"_json_pointer] = 27;
|
||||||
|
CHECK(j == json({{"this", {{"that", 27}}}}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue