a more forgiving array behavior
This commit is contained in:
parent
1cd256a95e
commit
bc2e3a798d
4 changed files with 48 additions and 10 deletions
|
@ -29,7 +29,7 @@ Other aspects were not so important to us:
|
||||||
As of February 2015, the following updates were made to the library
|
As of February 2015, the following updates were made to the library
|
||||||
|
|
||||||
- *Changed:* In the generic class `basic_json`, all JSON value types (array, object, string, bool, integer number, and floating-point) are now **templated**. That is, you can choose whether you like a `std::list` for your arrays or an `std::unordered_map` for your objects. The specialization `json` sets some reasonable defaults.
|
- *Changed:* In the generic class `basic_json`, all JSON value types (array, object, string, bool, integer number, and floating-point) are now **templated**. That is, you can choose whether you like a `std::list` for your arrays or an `std::unordered_map` for your objects. The specialization `json` sets some reasonable defaults.
|
||||||
- *Changed:* The library now consists of a single header, called `json.hpp`. Consequently, build systems such as Automake or CMake are not any longer required.
|
- *Changed:* The library now consists of a **single header**, called `json.hpp`. Consequently, build systems such as Automake or CMake are not any longer required.
|
||||||
- *Changed:* The **deserialization** is now supported by a lexer generated with [re2c](http://re2c.org) from file [`src/json.hpp.re2c`](https://github.com/nlohmann/json/blob/master/src/json.hpp.re2c). As a result, we follow the JSON specification more strictly. Note neither the tool re2c nor its input are required to use the class.
|
- *Changed:* The **deserialization** is now supported by a lexer generated with [re2c](http://re2c.org) from file [`src/json.hpp.re2c`](https://github.com/nlohmann/json/blob/master/src/json.hpp.re2c). As a result, we follow the JSON specification more strictly. Note neither the tool re2c nor its input are required to use the class.
|
||||||
- *Added:* The library now satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement. It hence provides four different iterators (`iterator`, `const_iterator`, `reverse_iterator`, and `const_reverse_iterator`), comparison functions, `swap()`, `size()`, `max_size()`, and `empty()` member functions.
|
- *Added:* The library now satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement. It hence provides four different iterators (`iterator`, `const_iterator`, `reverse_iterator`, and `const_reverse_iterator`), comparison functions, `swap()`, `size()`, `max_size()`, and `empty()` member functions.
|
||||||
- *Added*: The class uses **user-defined allocators** which default to `std::allocator`, but can be templated via parameter `Allocator`.
|
- *Added*: The class uses **user-defined allocators** which default to `std::allocator`, but can be templated via parameter `Allocator`.
|
||||||
|
@ -184,7 +184,7 @@ These operators work for any subclasses of `std::istream` or `std::ostream`.
|
||||||
|
|
||||||
### STL-like access
|
### STL-like access
|
||||||
|
|
||||||
We designed the JSON class to behave just like an STL container:
|
We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// create an array using push_back
|
// create an array using push_back
|
||||||
|
|
18
src/json.hpp
18
src/json.hpp
|
@ -712,12 +712,26 @@ class basic_json
|
||||||
/// access specified element
|
/// access specified element
|
||||||
inline reference operator[](size_type pos)
|
inline reference operator[](size_type pos)
|
||||||
{
|
{
|
||||||
// at only works for arrays
|
// implicitly convert null to object
|
||||||
|
if (m_type == value_t::null)
|
||||||
|
{
|
||||||
|
m_type = value_t::array;
|
||||||
|
Allocator<array_t> alloc;
|
||||||
|
m_value.array = alloc.allocate(1);
|
||||||
|
alloc.construct(m_value.array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [] only works for arrays
|
||||||
if (m_type != value_t::array)
|
if (m_type != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot use [] with " + type_name());
|
throw std::runtime_error("cannot use [] with " + type_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = m_value.array->size(); i <= pos; ++i)
|
||||||
|
{
|
||||||
|
m_value.array->push_back(basic_json());
|
||||||
|
}
|
||||||
|
|
||||||
return m_value.array->operator[](pos);
|
return m_value.array->operator[](pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +783,7 @@ class basic_json
|
||||||
alloc.construct(m_value.object);
|
alloc.construct(m_value.object);
|
||||||
}
|
}
|
||||||
|
|
||||||
// at only works for objects
|
// [] only works for objects
|
||||||
if (m_type != value_t::object)
|
if (m_type != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot use [] with " + type_name());
|
throw std::runtime_error("cannot use [] with " + type_name());
|
||||||
|
|
|
@ -712,12 +712,26 @@ class basic_json
|
||||||
/// access specified element
|
/// access specified element
|
||||||
inline reference operator[](size_type pos)
|
inline reference operator[](size_type pos)
|
||||||
{
|
{
|
||||||
// at only works for arrays
|
// implicitly convert null to object
|
||||||
|
if (m_type == value_t::null)
|
||||||
|
{
|
||||||
|
m_type = value_t::array;
|
||||||
|
Allocator<array_t> alloc;
|
||||||
|
m_value.array = alloc.allocate(1);
|
||||||
|
alloc.construct(m_value.array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [] only works for arrays
|
||||||
if (m_type != value_t::array)
|
if (m_type != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot use [] with " + type_name());
|
throw std::runtime_error("cannot use [] with " + type_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = m_value.array->size(); i <= pos; ++i)
|
||||||
|
{
|
||||||
|
m_value.array->push_back(basic_json());
|
||||||
|
}
|
||||||
|
|
||||||
return m_value.array->operator[](pos);
|
return m_value.array->operator[](pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +783,7 @@ class basic_json
|
||||||
alloc.construct(m_value.object);
|
alloc.construct(m_value.object);
|
||||||
}
|
}
|
||||||
|
|
||||||
// at only works for objects
|
// [] only works for objects
|
||||||
if (m_type != value_t::object)
|
if (m_type != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot use [] with " + type_name());
|
throw std::runtime_error("cannot use [] with " + type_name());
|
||||||
|
|
|
@ -2033,10 +2033,20 @@ TEST_CASE("element access")
|
||||||
{
|
{
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::null);
|
SECTION("standard tests")
|
||||||
const json j_nonarray_const(j_nonarray);
|
{
|
||||||
CHECK_THROWS_AS(j_nonarray[0], std::runtime_error);
|
json j_nonarray(json::value_t::null);
|
||||||
CHECK_THROWS_AS(j_nonarray_const[0], std::runtime_error);
|
const json j_nonarray_const(j_nonarray);
|
||||||
|
CHECK_NOTHROW(j_nonarray[0]);
|
||||||
|
CHECK_THROWS_AS(j_nonarray_const[0], std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("implicit transformation to properly filled array")
|
||||||
|
{
|
||||||
|
json j_nonarray;
|
||||||
|
j_nonarray[3] = 42;
|
||||||
|
CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
|
|
Loading…
Reference in a new issue