Skip to content

Commit

Permalink
Re-template json_pointer on string type (#3415)
Browse files Browse the repository at this point in the history
* Make exception context optional

Change exception context parameter to pointer and replace context with
nullptr where appropriate.

* Support escaping other string types

* Add string concatenation function

Add variadic concat() function for concatenating char *, char, and
string types.

* Replace string concatenations using + with concat()

* Template json_pointer on string type

Change json_pointer from being templated on basic_json to being
templated on string type.

* Add unit test for #3388

Closes #3388.

* Fix regression test for #2958

* Add backwards compatibility with json_pointer<basic_json>

* Update json_pointer docs

* Allow comparing different json_pointers

* Update version numbers
  • Loading branch information
falbrechtskirchinger authored Apr 12, 2022
1 parent 1deeb43 commit 616caea
Show file tree
Hide file tree
Showing 28 changed files with 1,712 additions and 858 deletions.
5 changes: 3 additions & 2 deletions doc/mkdocs/docs/api/json_pointer/back.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <small>nlohmann::json_pointer::</small>back

```cpp
const std::string& back() const;
const string_t& back() const;
```

Return last reference token.
Expand Down Expand Up @@ -36,4 +36,5 @@ Constant.

## Version history

Added in version 3.6.0.
- Added in version 3.6.0.
- Changed return type to `string_t` in version 3.11.0.
19 changes: 14 additions & 5 deletions doc/mkdocs/docs/api/json_pointer/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <small>nlohmann::</small>json_pointer

```cpp
template<typename BasicJsonType>
template<typename RefStringType>
class json_pointer;
```

Expand All @@ -11,14 +11,18 @@ are the base for JSON patches.

## Template parameters

`BasicJsonType`
: a specialization of [`basic_json`](../basic_json/index.md)
`RefStringType`
: the string type used for the reference tokens making up the JSON pointer

## Notes

For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is deprecated and may be removed in a future major version.

## Member functions

- [(constructor)](json_pointer.md)
- [**to_string**](to_string.md) - return a string representation of the JSON pointer
- [**operator std::string**](operator_string.md) - return a string representation of the JSON pointer
- [**operator string_t**](operator_string.md) - return a string representation of the JSON pointer
- [**operator/=**](operator_slasheq.md) - append to the end of the JSON pointer
- [**operator/**](operator_slash.md) - create JSON Pointer by appending
- [**parent_pointer**](parent_pointer.md) - returns the parent of this JSON pointer
Expand All @@ -27,11 +31,16 @@ are the base for JSON patches.
- [**push_back**](push_back.md) - append an unescaped token at the end of the pointer
- [**empty**](empty.md) - return whether pointer points to the root document

## Member types

- [**string_t**](string_t.md) - the string type used for the reference tokens

## See also

- [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers
- [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)

## Version history

Added in version 2.0.0.
- Added in version 2.0.0.
- Changed template parameter from `basic_json` to string type in version 3.11.0.
5 changes: 3 additions & 2 deletions doc/mkdocs/docs/api/json_pointer/json_pointer.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <small>nlohmann::json_pointer::</small>json_pointer

```cpp
explicit json_pointer(const std::string& s = "");
explicit json_pointer(const string_t& s = "");
```
Create a JSON pointer according to the syntax described in
Expand Down Expand Up @@ -37,4 +37,5 @@ Create a JSON pointer according to the syntax described in
## Version history
Added in version 2.0.0.
- Added in version 2.0.0.
- Changed type of `s` to `string_t` in version 3.11.0.
4 changes: 2 additions & 2 deletions doc/mkdocs/docs/api/json_pointer/operator_slash.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs);

// (2)
json_pointer operator/(const json_pointer& lhs, std::string token);
json_pointer operator/(const json_pointer& lhs, string_t token);

// (3)
json_pointer operator/(const json_pointer& lhs, std::size_t array_idx);
Expand Down Expand Up @@ -60,5 +60,5 @@ json_pointer operator/(const json_pointer& lhs, std::size_t array_idx);
## Version history

1. Added in version 3.6.0.
2. Added in version 3.6.0.
2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0.
3. Added in version 3.6.0.
4 changes: 2 additions & 2 deletions doc/mkdocs/docs/api/json_pointer/operator_slasheq.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
json_pointer& operator/=(const json_pointer& ptr);

// (2)
json_pointer& operator/=(std::string token);
json_pointer& operator/=(string_t token);

// (3)
json_pointer& operator/=(std::size_t array_idx)
Expand Down Expand Up @@ -57,5 +57,5 @@ json_pointer& operator/=(std::size_t array_idx)
## Version history

1. Added in version 3.6.0.
2. Added in version 3.6.0.
2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0.
3. Added in version 3.6.0.
9 changes: 5 additions & 4 deletions doc/mkdocs/docs/api/json_pointer/operator_string.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <small>nlohmann::json_pointer::</small>operator std::string
# <small>nlohmann::json_pointer::</small>operator string_t

```cpp
operator std::string() const
operator string_t() const
```

Return a string representation of the JSON pointer.
Expand All @@ -13,12 +13,13 @@ A string representation of the JSON pointer
## Possible implementation

```cpp
operator std::string() const
operator string_t() const
{
return to_string();
}
```

## Version history

Since version 2.0.0.
- Since version 2.0.0.
- Changed type to `string_t` in version 3.11.0.
7 changes: 4 additions & 3 deletions doc/mkdocs/docs/api/json_pointer/push_back.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# <small>nlohmann::json_pointer::</small>push_back

```cpp
void push_back(const std::string& token);
void push_back(const string_t& token);

void push_back(std::string&& token);
void push_back(string_t&& token);
```
Append an unescaped token at the end of the reference pointer.
Expand Down Expand Up @@ -35,4 +35,5 @@ Amortized constant.
## Version history
Added in version 3.6.0.
- Added in version 3.6.0.
- Changed type of `token` to `string_t` in version 3.11.0.
12 changes: 12 additions & 0 deletions doc/mkdocs/docs/api/json_pointer/string_t.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# <small>nlohmann::json_pointer::</small>string_t
```cpp
using string_t = RefStringType;
```

The string type used for the reference tokens making up the JSON pointer.

See [`basic_json::string_t`](../basic_json/string_t.md) for more information.

## Version history

- Added in version 3.11.0.
5 changes: 3 additions & 2 deletions doc/mkdocs/docs/api/json_pointer/to_string.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <small>nlohmann::json_pointer::</small>to_string

```cpp
std::string to_string() const;
string_t to_string() const;
```

Return a string representation of the JSON pointer.
Expand Down Expand Up @@ -36,4 +36,5 @@ ptr == json_pointer(ptr.to_string());

## Version history

Since version 2.0.0.
- Since version 2.0.0.
- Changed return type to `string_t` in version 3.11.0.
1 change: 1 addition & 0 deletions doc/mkdocs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ nav:
- 'parent_pointer': api/json_pointer/parent_pointer.md
- 'pop_back': api/json_pointer/pop_back.md
- 'push_back': api/json_pointer/push_back.md
- 'string_t': api/json_pointer/string_t.md
- 'to_string': api/json_pointer/to_string.md
- json_sax:
- 'Overview': api/json_sax/index.md
Expand Down
37 changes: 19 additions & 18 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/value_t.hpp>

#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
Expand All @@ -42,7 +43,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
}
n = nullptr;
}
Expand Down Expand Up @@ -80,7 +81,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}

Expand All @@ -89,7 +90,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
}
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
}
Expand All @@ -99,7 +100,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
Expand All @@ -114,7 +115,7 @@ void from_json(const BasicJsonType& j, StringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}

s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
Expand Down Expand Up @@ -154,7 +155,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
Expand All @@ -171,7 +172,7 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l),
Expand Down Expand Up @@ -268,7 +269,7 @@ void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}

from_json_array_impl(j, arr, priority_tag<3> {});
Expand All @@ -287,7 +288,7 @@ auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}

return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
Expand All @@ -298,7 +299,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
}

bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
Expand All @@ -310,7 +311,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
}

ConstructibleObjectType ret;
Expand Down Expand Up @@ -370,7 +371,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}

Expand Down Expand Up @@ -411,7 +412,7 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}

return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
Expand All @@ -424,14 +425,14 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
Expand All @@ -444,14 +445,14 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
Expand All @@ -463,7 +464,7 @@ void from_json(const BasicJsonType& j, std_fs::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
Expand Down
Loading

0 comments on commit 616caea

Please sign in to comment.