Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
5e1d0f15
Commit
5e1d0f15
authored
Jul 12, 2015
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more documentation and some cleanup
parent
c012b29a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
742 additions
and
156 deletions
+742
-156
src/json.hpp
src/json.hpp
+371
-78
src/json.hpp.re2c
src/json.hpp.re2c
+371
-78
No files found.
src/json.hpp
View file @
5e1d0f15
...
@@ -13,7 +13,6 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
...
@@ -13,7 +13,6 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
@see https://github.com/nlohmann/json to download the source code
@see https://github.com/nlohmann/json to download the source code
*/
*/
#ifndef NLOHMANN_JSON_HPP
#ifndef NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
...
@@ -87,20 +86,20 @@ static bool approx(const T a, const T b)
...
@@ -87,20 +86,20 @@ static bool approx(const T a, const T b)
/*!
/*!
@brief a class to store JSON values
@brief a class to store JSON values
@tparam ObjectType
type for JSON objects
@tparam ObjectType
type for JSON objects (@c std::map by default; will be used
(@c std::map by defaul
t)
in @ref object_
t)
@tparam ArrayType
type for JSON arrays
@tparam ArrayType
type for JSON arrays (@c std::vector by default; will be used
(@c std::vector by defaul
t)
in @ref array_
t)
@tparam StringType
type for JSON strings and object keys
@tparam StringType
type for JSON strings and object keys (@c std::string by
(@c std::string by defaul
t)
default; will be used in @ref string_
t)
@tparam BooleanType
type for JSON booleans
@tparam BooleanType
type for JSON booleans (@c `bool` by default; will be used
(@c bool by defaul
t)
in @ref boolean_
t)
@tparam NumberIntegerType
type for JSON integer numbers
@tparam NumberIntegerType
type for JSON integer numbers (@c `int64_t` by
(@c int64_t by defaul
t)
default; will be used in @ref number_integer_
t)
@tparam NumberFloatType
type for JSON floating-point numbers
@tparam NumberFloatType
type for JSON floating-point numbers (@c `double` by
(@c double by defaul
t)
default; will be used in @ref number_float_
t)
@tparam AllocatorType
type of the allocator to use
@tparam AllocatorType
type of the allocator to use (@c `std::allocator` by
(@c std::allocator by
default)
default)
@requirement This class satisfies the Container requirements (see
@requirement This class satisfies the Container requirements (see
http://en.cppreference.com/w/cpp/concept/Container):
http://en.cppreference.com/w/cpp/concept/Container):
...
@@ -195,21 +194,305 @@ class basic_json
...
@@ -195,21 +194,305 @@ class basic_json
/// @name JSON value data types
/// @name JSON value data types
/// @{
/// @{
/// a type for an object
/*!
@brief a type for an object
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
> An object is an unordered collection of zero or more name/value pairs,
> where a name is a string and a value is a string, number, boolean, null,
> object, or array.
To store objects in C++, a type is defined by the template parameters @a
ObjectType which chooses the container (e.g., `std::map` or
`std::unordered_map`), @a StringType which chooses the type of the keys or
names, and @a AllocatorType which chooses the allocator to use.
#### Default type
With the default values for @a ObjectType (`std::map`), @a StringType
(`std::string`), and @a AllocatorType (`std::allocator`), the default value
for @a object_t is:
@code {.cpp}
std::map<
std::string, // key_type
basic_json, // value_type
std::less<std::string>, // key_compare
std::allocator<std::pair<const std::string, basic_json>> // allocator_type
>
@endcode
#### Behavior
The choice of @a object_t influences the behavior of the JSON class. With
the default type, objects have the following behavior:
- When all names are unique, objects will be interoperable in the sense
that all software implementations receiving that object will agree on the
name-value mappings.
- When the names within an object are not unique, later stored name/value
pairs overwrite previously stored name/value pairs, leaving the used
names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
be treated as equal and both stored as `{"key": 1}`.
- Internally, name/value pairs are stored in lexicographical order of the
names. Objects will also be serialized (see @ref dump) in this order. For
instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and
serialized as `{"a": 2, "b": 1}`.
- When comparing objects, the order of the name/value pairs is irrelevant.
This makes objects interoperable in the sense that they will not be
affected by these differences. For instance, `{"b": 1, "a": 2}` and
`{"a": 2, "b": 1}` will be treated as equal.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
In this class, the object's limit of nesting is not constraint explicitly.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the @ref
max_size function of a JSON object.
#### Storage
Objects are stored as pointers in a `basic_json` type. That is, for any
access to object values, a pointer of type `object_t*` must be dereferenced.
@sa array_t
*/
using
object_t
=
using
object_t
=
ObjectType
<
StringType
,
basic_json
,
std
::
less
<
StringType
>
,
AllocatorType
<
std
::
pair
<
const
StringType
,
basic_json
>>>
;
ObjectType
<
StringType
,
basic_json
,
std
::
less
<
StringType
>
,
AllocatorType
<
std
::
pair
<
const
StringType
,
basic_json
>>>
;
/// a type for an array
/*!
@brief a type for an array
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
> An array is an ordered sequence of zero or more values.
To store objects in C++, a type is defined by the template parameters @a
ArrayType which chooses the container (e.g., `std::vector` or `std::list`)
and @a AllocatorType which chooses the allocator to use.
#### Default type
With the default values for @a ArrayType (`std::vector`) and @a
AllocatorType (`std::allocator`), the default value for @a array_t is:
@code {.cpp}
std::vector<
basic_json, // value_type
std::allocator<basic_json> // allocator_type
>
@endcode
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
In this class, the array's limit of nesting is not constraint explicitly.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the @ref
max_size function of a JSON array.
#### Storage
Arrays are stored as pointers in a `basic_json` type. That is, for any
access to array values, a pointer of type `array_t*` must be dereferenced.
*/
using
array_t
=
ArrayType
<
basic_json
,
AllocatorType
<
basic_json
>>
;
using
array_t
=
ArrayType
<
basic_json
,
AllocatorType
<
basic_json
>>
;
/// a type for a string
/*!
@brief a type for a string
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
> A string is a sequence of zero or more Unicode characters.
To store objects in C++, a type is defined by the template parameters @a
StringType which chooses the container (e.g., `std::string`) to use.
Unicode values are split by the JSON class into byte-sized characters
during deserialization.
#### Default type
With the default values for @a StringType (`std::string`), the default
value for @a string_t is:
@code {.cpp}
std::string
@endcode
#### String comparison
[RFC 7159](http://rfc7159.net/rfc7159) states:
> Software implementations are typically required to test names of object
> members for equality. Implementations that transform the textual
> representation into sequences of Unicode code units and then perform the
> comparison numerically, code unit by code unit, are interoperable in the
> sense that implementations will agree in all cases on equality or
> inequality of two strings. For example, implementations that compare
> strings with escaped characters unconverted may incorrectly find that
> `"a\\b"` and `"a\u005Cb"` are not equal.
This implementation is interoperable as it does compare strings code unit
by code unit.
#### Storage
String values are stored as pointers in a `basic_json` type. That is, for
any access to string values, a pointer of type `string_t*` must be
dereferenced.
*/
using
string_t
=
StringType
;
using
string_t
=
StringType
;
/// a type for a boolean
/*!
@brief a type for a boolean
[RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
type which differentiates the two literals `true` and `false`.
To store objects in C++, a type is defined by the template parameter @a
BooleanType which chooses the type to use.
#### Default type
With the default values for @a BooleanType (`bool`), the default value for
@a boolean_t is:
@code {.cpp}
bool
@endcode
#### Storage
Boolean values are stored directly inside a `basic_json` type.
*/
using
boolean_t
=
BooleanType
;
using
boolean_t
=
BooleanType
;
/// a type for a number (integer)
/*!
@brief a type for a number (integer)
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
> The representation of numbers is similar to that used in most programming
> languages. A number is represented in base 10 using decimal digits. It
> contains an integer component that may be prefixed with an optional minus
> sign, which may be followed by a fraction part and/or an exponent part.
> Leading zeros are not allowed. (...) Numeric values that cannot be
> represented in the grammar below (such as Infinity and NaN) are not
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is an
integer or a floating-point number. Therefore, two different types, @ref
number_integer_t and @ref number_float_t are used.
To store integer numbers in C++, a type is defined by the template
parameter @a NumberIntegerType which chooses the type to use.
#### Default type
With the default values for @a NumberIntegerType (`int64_t`), the default
value for @a number_integer_t is:
@code {.cpp}
int64_t
@endcode
#### Default behavior
- The restrictions about leading zeros is not enforced in C++. Instead,
leading zeros in integer literals lead to an interpretation as octal
number. Internally, the value will be stored as decimal number. For
instance, the C++ integer literal `010` will be serialized to `8`. During
deserialization, leading zeros yield an error.
- Not-a-number (NaN) values will be serialized to `null`.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the range and precision of numbers.
When the default type is used, the maximal integer number that can be
stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
that are out of range will yield over/underflow when used in a constructor.
During deserialization, too large or small integer numbers will be
automatically be stored as @ref number_float_t.
[RFC 7159](http://rfc7159.net/rfc7159) further states:
> Note that when such software is used, numbers that are integers and are
> in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
> that implementations will agree exactly on their numeric values.
As this range is a subrange of the exactly supported range [INT64_MIN,
INT64_MAX], this class's integer type is interoperable.
#### Storage
Integer number values are stored directly inside a `basic_json` type.
*/
using
number_integer_t
=
NumberIntegerType
;
using
number_integer_t
=
NumberIntegerType
;
/// a type for a number (floating-point)
/*!
@brief a type for a number (floating-point)
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
> The representation of numbers is similar to that used in most programming
> languages. A number is represented in base 10 using decimal digits. It
> contains an integer component that may be prefixed with an optional minus
> sign, which may be followed by a fraction part and/or an exponent part.
> Leading zeros are not allowed. (...) Numeric values that cannot be
> represented in the grammar below (such as Infinity and NaN) are not
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is an
integer or a floating-point number. Therefore, two different types, @ref
number_integer_t and @ref number_float_t are used.
To store floating-point numbers in C++, a type is defined by the template
parameter @a NumberFloatType which chooses the type to use.
#### Default type
With the default values for @a NumberFloatType (`double`), the default
value for @a number_float_t is:
@code {.cpp}
double
@endcode
#### Default behavior
- The restrictions about leading zeros is not enforced in C++. Instead,
leading zeros in floating-point literals will be ignored. Internally, the
value will be stored as decimal number. For instance, the C++
floating-point literal `01.2` will be serialized to `1.2`. During
deserialization, leading zeros yield an error.
- Not-a-number (NaN) values will be serialized to `null`.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) states:
> This specification allows implementations to set limits on the range and
> precision of numbers accepted. Since software that implements IEEE
> 754-2008 binary64 (double precision) numbers is generally available and
> widely used, good interoperability can be achieved by implementations that
> expect no more precision or range than these provide, in the sense that
> implementations will approximate JSON numbers within the expected
> precision.
This implementation does exactly follow this approach, as it uses double
precision floating-point numbers. Note values smaller than
`-1.79769313486232e+308` and values greather than `1.79769313486232e+308`
will be stored as NaN internally and be serialized to `null`.
#### Storage
Floating-point number values are stored directly inside a `basic_json` type.
*/
using
number_float_t
=
NumberFloatType
;
using
number_float_t
=
NumberFloatType
;
/// a type for list initialization
using
list_init_t
=
std
::
initializer_list
<
basic_json
>
;
/// @}
/// @}
...
@@ -425,35 +708,6 @@ class basic_json
...
@@ -425,35 +708,6 @@ class basic_json
using
parser_callback_t
=
std
::
function
<
bool
(
using
parser_callback_t
=
std
::
function
<
bool
(
int
depth
,
parse_event_t
event
,
basic_json
&
parsed
)
>
;
int
depth
,
parse_event_t
event
,
basic_json
&
parsed
)
>
;
/*!
@brief comparison operator for JSON types
Returns an ordering that is similar to Python:
- order: null < boolean < number < object < array < string
- furthermore, each type is not smaller than itself
*/
friend
bool
operator
<
(
const
value_t
lhs
,
const
value_t
rhs
)
{
static
constexpr
std
::
array
<
uint8_t
,
7
>
order
=
{{
0
,
// null
3
,
// object
4
,
// array
5
,
// string
1
,
// boolean
2
,
// integer
2
// float
}
};
// discarded values are not comparable
if
(
lhs
==
value_t
::
discarded
or
rhs
==
value_t
::
discarded
)
{
return
false
;
}
return
order
[
static_cast
<
std
::
size_t
>
(
lhs
)]
<
order
[
static_cast
<
std
::
size_t
>
(
rhs
)];
}
//////////////////
//////////////////
// constructors //
// constructors //
...
@@ -911,10 +1165,11 @@ class basic_json
...
@@ -911,10 +1165,11 @@ class basic_json
With the rules described above, the following JSON values cannot be
With the rules described above, the following JSON values cannot be
expressed by an initializer list:
expressed by an initializer list:
- the empty array (`[]`): use @ref array(list_init_t) with an empty
- the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
initializer list in this case
with an empty initializer list in this case
- arrays whose elements satisfy rule 2: use @ref array(list_init_t) with
- arrays whose elements satisfy rule 2: use @ref
the same initializer list in this case
array(std::initializer_list<basic_json>) with the same initializer list
in this case
@note When used without parentheses around an empty initializer list, @ref
@note When used without parentheses around an empty initializer list, @ref
basic_json() is called instead of this function, yielding the JSON null
basic_json() is called instead of this function, yielding the JSON null
...
@@ -925,7 +1180,8 @@ class basic_json
...
@@ -925,7 +1180,8 @@ class basic_json
@param[in] type_deduction internal parameter; when set to `true`, the type
@param[in] type_deduction internal parameter; when set to `true`, the type
of the JSON value is deducted from the initializer list @a init; when set
of the JSON value is deducted from the initializer list @a init; when set
to `false`, the type provided via @a manual_type is forced. This mode is
to `false`, the type provided via @a manual_type is forced. This mode is
used by the functions @ref array(list_init_t) and @ref object(list_init_t).
used by the functions @ref array(std::initializer_list<basic_json>) and
@ref object(std::initializer_list<basic_json>).
@param[in] manual_type internal parameter; when @a type_deduction is set to
@param[in] manual_type internal parameter; when @a type_deduction is set to
`false`, the created JSON value will use the provided type (only @ref
`false`, the created JSON value will use the provided type (only @ref
...
@@ -941,12 +1197,13 @@ class basic_json
...
@@ -941,12 +1197,13 @@ class basic_json
@liveexample{The example below shows how JSON values are created from
@liveexample{The example below shows how JSON values are created from
initializer lists,basic_json__list_init_t}
initializer lists,basic_json__list_init_t}
@sa basic_json array(
list_init_t) - create a JSON array value from an
@sa basic_json array(
std::initializer_list<basic_json>) - create a JSON
initializer list
array value from an
initializer list
@sa basic_json object(
list_init_t) - create a JSON object value from an
@sa basic_json object(
std::initializer_list<basic_json>) - create a JSON
initializer list
object value from an
initializer list
*/
*/
basic_json
(
list_init_t
init
,
bool
type_deduction
=
true
,
basic_json
(
std
::
initializer_list
<
basic_json
>
init
,
bool
type_deduction
=
true
,
value_t
manual_type
=
value_t
::
array
)
value_t
manual_type
=
value_t
::
array
)
{
{
// the initializer list could describe an object
// the initializer list could describe an object
...
@@ -1012,7 +1269,8 @@ class basic_json
...
@@ -1012,7 +1269,8 @@ class basic_json
@note This function is only needed to express two edge cases that cannot be
@note This function is only needed to express two edge cases that cannot be
realized with the initializer list constructor (@ref
realized with the initializer list constructor (@ref
basic_json(list_init_t, bool, value_t)). These cases are:
basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
are:
1. creating an array whose elements are all pairs whose first element is a
1. creating an array whose elements are all pairs whose first element is a
string - in this case, the initializer list constructor would create an
string - in this case, the initializer list constructor would create an
object, taking the first elements as keys
object, taking the first elements as keys
...
@@ -1029,12 +1287,13 @@ class basic_json
...
@@ -1029,12 +1287,13 @@ class basic_json
@liveexample{The following code shows an example for the @ref array
@liveexample{The following code shows an example for the @ref array
function.,array}
function.,array}
@sa basic_json(
list_init_t, bool, value_t) - create a JSON value from an
@sa basic_json(
std::initializer_list<basic_json>, bool, value_t) - create a
initializer list
JSON value from an
initializer list
@sa basic_json object(
list_init_t) - create a JSON object value from an
@sa basic_json object(
std::initializer_list<basic_json>) - create a JSON
initializer list
object value from an
initializer list
*/
*/
static
basic_json
array
(
list_init_t
init
=
list_init_t
())
static
basic_json
array
(
std
::
initializer_list
<
basic_json
>
init
=
std
::
initializer_list
<
basic_json
>
())
{
{
return
basic_json
(
init
,
false
,
value_t
::
array
);
return
basic_json
(
init
,
false
,
value_t
::
array
);
}
}
...
@@ -1047,29 +1306,32 @@ class basic_json
...
@@ -1047,29 +1306,32 @@ class basic_json
the initializer list is empty, the empty object `{}` is created.
the initializer list is empty, the empty object `{}` is created.
@note This function is only added for symmetry reasons. In contrast to the
@note This function is only added for symmetry reasons. In contrast to the
related function @ref basic_json array(list_init_t), there are no cases
related function @ref basic_json array(std::initializer_list<basic_json>),
which can only be expressed by this function. That is, any initializer list
there are no cases which can only be expressed by this function. That is,
@a init can also be passed to the initializer list constructor @ref
any initializer list @a init can also be passed to the initializer list
basic_json(list_init_t, bool, value_t).
constructor @ref basic_json(std::initializer_list<basic_json>, bool,
value_t).
@param[in] init initializer list to create an object from (optional)
@param[in] init initializer list to create an object from (optional)
@return JSON object value
@return JSON object value
@throw std::domain_error if @a init is not a pair whose first elements are
@throw std::domain_error if @a init is not a pair whose first elements are
strings; thrown by @ref basic_json(list_init_t, bool, value_t)
strings; thrown by @ref basic_json(std::initializer_list<basic_json>, bool,
value_t)
@complexity Linear in the size of @a init.
@complexity Linear in the size of @a init.
@liveexample{The following code shows an example for the @ref object
@liveexample{The following code shows an example for the @ref object
function.,object}
function.,object}
@sa basic_json(
list_init_t, bool, value_t) - create a JSON value from an
@sa basic_json(
std::initializer_list<basic_json>, bool, value_t) - create a
initializer list
JSON value from an
initializer list
@sa basic_json array(
list_init_t) - create a JSON array value from an
@sa basic_json array(
std::initializer_list<basic_json>) - create a JSON
initializer list
array value from an
initializer list
*/
*/
static
basic_json
object
(
list_init_t
init
=
list_init_t
())
static
basic_json
object
(
std
::
initializer_list
<
basic_json
>
init
=
std
::
initializer_list
<
basic_json
>
())
{
{
return
basic_json
(
init
,
false
,
value_t
::
object
);
return
basic_json
(
init
,
false
,
value_t
::
object
);
}
}
...
@@ -3592,6 +3854,37 @@ class basic_json
...
@@ -3592,6 +3854,37 @@ class basic_json
/// @name lexicographical comparison operators
/// @name lexicographical comparison operators
/// @{
/// @{
private:
/*!
@brief comparison operator for JSON types
Returns an ordering that is similar to Python:
- order: null < boolean < number < object < array < string
- furthermore, each type is not smaller than itself
*/
friend
bool
operator
<
(
const
value_t
lhs
,
const
value_t
rhs
)
{
static
constexpr
std
::
array
<
uint8_t
,
7
>
order
=
{{
0
,
// null
3
,
// object
4
,
// array
5
,
// string
1
,
// boolean
2
,
// integer
2
// float
}
};
// discarded values are not comparable
if
(
lhs
==
value_t
::
discarded
or
rhs
==
value_t
::
discarded
)
{
return
false
;
}
return
order
[
static_cast
<
std
::
size_t
>
(
lhs
)]
<
order
[
static_cast
<
std
::
size_t
>
(
rhs
)];
}
public:
/*!
/*!
@brief comparison: equal
@brief comparison: equal
...
...
src/json.hpp.re2c
View file @
5e1d0f15
...
@@ -13,7 +13,6 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
...
@@ -13,7 +13,6 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
@see https://github.com/nlohmann/json to download the source code
@see https://github.com/nlohmann/json to download the source code
*/
*/
#ifndef NLOHMANN_JSON_HPP
#ifndef NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
...
@@ -87,20 +86,20 @@ static bool approx(const T a, const T b)
...
@@ -87,20 +86,20 @@ static bool approx(const T a, const T b)
/*!
/*!
@brief a class to store JSON values
@brief a class to store JSON values
@tparam ObjectType
type for JSON objects
@tparam ObjectType
type for JSON objects (@c std::map by default; will be used
(@c std::map by defaul
t)
in @ref object_
t)
@tparam ArrayType
type for JSON arrays
@tparam ArrayType
type for JSON arrays (@c std::vector by default; will be used
(@c std::vector by defaul
t)
in @ref array_
t)
@tparam StringType
type for JSON strings and object keys
@tparam StringType
type for JSON strings and object keys (@c std::string by
(@c std::string by defaul
t)
default; will be used in @ref string_
t)
@tparam BooleanType
type for JSON booleans
@tparam BooleanType
type for JSON booleans (@c `bool` by default; will be used
(@c bool by defaul
t)
in @ref boolean_
t)
@tparam NumberIntegerType
type for JSON integer numbers
@tparam NumberIntegerType
type for JSON integer numbers (@c `int64_t` by
(@c int64_t by defaul
t)
default; will be used in @ref number_integer_
t)
@tparam NumberFloatType
type for JSON floating-point numbers
@tparam NumberFloatType
type for JSON floating-point numbers (@c `double` by
(@c double by defaul
t)
default; will be used in @ref number_float_
t)
@tparam AllocatorType
type of the allocator to use
@tparam AllocatorType
type of the allocator to use (@c `std::allocator` by
(@c std::allocator by
default)
default)
@requirement This class satisfies the Container requirements (see
@requirement This class satisfies the Container requirements (see
http://en.cppreference.com/w/cpp/concept/Container):
http://en.cppreference.com/w/cpp/concept/Container):
...
@@ -195,21 +194,305 @@ class basic_json
...
@@ -195,21 +194,305 @@ class basic_json
/// @name JSON value data types
/// @name JSON value data types
/// @{
/// @{
/// a type for an object
/*!
@brief a type for an object
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
> An object is an unordered collection of zero or more name/value pairs,
> where a name is a string and a value is a string, number, boolean, null,
> object, or array.
To store objects in C++, a type is defined by the template parameters @a
ObjectType which chooses the container (e.g., `std::map` or
`std::unordered_map`), @a StringType which chooses the type of the keys or
names, and @a AllocatorType which chooses the allocator to use.
#### Default type
With the default values for @a ObjectType (`std::map`), @a StringType
(`std::string`), and @a AllocatorType (`std::allocator`), the default value
for @a object_t is:
@code {.cpp}
std::map<
std::string, // key_type
basic_json, // value_type
std::less<std::string>, // key_compare
std::allocator<std::pair<const std::string, basic_json>> // allocator_type
>
@endcode
#### Behavior
The choice of @a object_t influences the behavior of the JSON class. With
the default type, objects have the following behavior:
- When all names are unique, objects will be interoperable in the sense
that all software implementations receiving that object will agree on the
name-value mappings.
- When the names within an object are not unique, later stored name/value
pairs overwrite previously stored name/value pairs, leaving the used
names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
be treated as equal and both stored as `{"key": 1}`.
- Internally, name/value pairs are stored in lexicographical order of the
names. Objects will also be serialized (see @ref dump) in this order. For
instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and
serialized as `{"a": 2, "b": 1}`.
- When comparing objects, the order of the name/value pairs is irrelevant.
This makes objects interoperable in the sense that they will not be
affected by these differences. For instance, `{"b": 1, "a": 2}` and
`{"a": 2, "b": 1}` will be treated as equal.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
In this class, the object's limit of nesting is not constraint explicitly.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the @ref
max_size function of a JSON object.
#### Storage
Objects are stored as pointers in a `basic_json` type. That is, for any
access to object values, a pointer of type `object_t*` must be dereferenced.
@sa array_t
*/
using object_t =
using object_t =
ObjectType<StringType, basic_json, std::less<StringType>, AllocatorType<std::pair<const StringType, basic_json>>>;
ObjectType<StringType, basic_json, std::less<StringType>, AllocatorType<std::pair<const StringType, basic_json>>>;
/// a type for an array
/*!
@brief a type for an array
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
> An array is an ordered sequence of zero or more values.
To store objects in C++, a type is defined by the template parameters @a
ArrayType which chooses the container (e.g., `std::vector` or `std::list`)
and @a AllocatorType which chooses the allocator to use.
#### Default type
With the default values for @a ArrayType (`std::vector`) and @a
AllocatorType (`std::allocator`), the default value for @a array_t is:
@code {.cpp}
std::vector<
basic_json, // value_type
std::allocator<basic_json> // allocator_type
>
@endcode
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
In this class, the array's limit of nesting is not constraint explicitly.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the @ref
max_size function of a JSON array.
#### Storage
Arrays are stored as pointers in a `basic_json` type. That is, for any
access to array values, a pointer of type `array_t*` must be dereferenced.
*/
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
/// a type for a string
/*!
@brief a type for a string
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
> A string is a sequence of zero or more Unicode characters.
To store objects in C++, a type is defined by the template parameters @a
StringType which chooses the container (e.g., `std::string`) to use.
Unicode values are split by the JSON class into byte-sized characters
during deserialization.
#### Default type
With the default values for @a StringType (`std::string`), the default
value for @a string_t is:
@code {.cpp}
std::string
@endcode
#### String comparison
[RFC 7159](http://rfc7159.net/rfc7159) states:
> Software implementations are typically required to test names of object
> members for equality. Implementations that transform the textual
> representation into sequences of Unicode code units and then perform the
> comparison numerically, code unit by code unit, are interoperable in the
> sense that implementations will agree in all cases on equality or
> inequality of two strings. For example, implementations that compare
> strings with escaped characters unconverted may incorrectly find that
> `"a\\b"` and `"a\u005Cb"` are not equal.
This implementation is interoperable as it does compare strings code unit
by code unit.
#### Storage
String values are stored as pointers in a `basic_json` type. That is, for
any access to string values, a pointer of type `string_t*` must be
dereferenced.
*/
using string_t = StringType;
using string_t = StringType;
/// a type for a boolean
/*!
@brief a type for a boolean
[RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
type which differentiates the two literals `true` and `false`.
To store objects in C++, a type is defined by the template parameter @a
BooleanType which chooses the type to use.
#### Default type
With the default values for @a BooleanType (`bool`), the default value for
@a boolean_t is:
@code {.cpp}
bool
@endcode
#### Storage
Boolean values are stored directly inside a `basic_json` type.
*/
using boolean_t = BooleanType;
using boolean_t = BooleanType;
/// a type for a number (integer)
/*!
@brief a type for a number (integer)
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
> The representation of numbers is similar to that used in most programming
> languages. A number is represented in base 10 using decimal digits. It
> contains an integer component that may be prefixed with an optional minus
> sign, which may be followed by a fraction part and/or an exponent part.
> Leading zeros are not allowed. (...) Numeric values that cannot be
> represented in the grammar below (such as Infinity and NaN) are not
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is an
integer or a floating-point number. Therefore, two different types, @ref
number_integer_t and @ref number_float_t are used.
To store integer numbers in C++, a type is defined by the template
parameter @a NumberIntegerType which chooses the type to use.
#### Default type
With the default values for @a NumberIntegerType (`int64_t`), the default
value for @a number_integer_t is:
@code {.cpp}
int64_t
@endcode
#### Default behavior
- The restrictions about leading zeros is not enforced in C++. Instead,
leading zeros in integer literals lead to an interpretation as octal
number. Internally, the value will be stored as decimal number. For
instance, the C++ integer literal `010` will be serialized to `8`. During
deserialization, leading zeros yield an error.
- Not-a-number (NaN) values will be serialized to `null`.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the range and precision of numbers.
When the default type is used, the maximal integer number that can be
stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
that are out of range will yield over/underflow when used in a constructor.
During deserialization, too large or small integer numbers will be
automatically be stored as @ref number_float_t.
[RFC 7159](http://rfc7159.net/rfc7159) further states:
> Note that when such software is used, numbers that are integers and are
> in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
> that implementations will agree exactly on their numeric values.
As this range is a subrange of the exactly supported range [INT64_MIN,
INT64_MAX], this class's integer type is interoperable.
#### Storage
Integer number values are stored directly inside a `basic_json` type.
*/
using number_integer_t = NumberIntegerType;
using number_integer_t = NumberIntegerType;
/// a type for a number (floating-point)
/*!
@brief a type for a number (floating-point)
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
> The representation of numbers is similar to that used in most programming
> languages. A number is represented in base 10 using decimal digits. It
> contains an integer component that may be prefixed with an optional minus
> sign, which may be followed by a fraction part and/or an exponent part.
> Leading zeros are not allowed. (...) Numeric values that cannot be
> represented in the grammar below (such as Infinity and NaN) are not
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is an
integer or a floating-point number. Therefore, two different types, @ref
number_integer_t and @ref number_float_t are used.
To store floating-point numbers in C++, a type is defined by the template
parameter @a NumberFloatType which chooses the type to use.
#### Default type
With the default values for @a NumberFloatType (`double`), the default
value for @a number_float_t is:
@code {.cpp}
double
@endcode
#### Default behavior
- The restrictions about leading zeros is not enforced in C++. Instead,
leading zeros in floating-point literals will be ignored. Internally, the
value will be stored as decimal number. For instance, the C++
floating-point literal `01.2` will be serialized to `1.2`. During
deserialization, leading zeros yield an error.
- Not-a-number (NaN) values will be serialized to `null`.
#### Limits
[RFC 7159](http://rfc7159.net/rfc7159) states:
> This specification allows implementations to set limits on the range and
> precision of numbers accepted. Since software that implements IEEE
> 754-2008 binary64 (double precision) numbers is generally available and
> widely used, good interoperability can be achieved by implementations that
> expect no more precision or range than these provide, in the sense that
> implementations will approximate JSON numbers within the expected
> precision.
This implementation does exactly follow this approach, as it uses double
precision floating-point numbers. Note values smaller than
`-1.79769313486232e+308` and values greather than `1.79769313486232e+308`
will be stored as NaN internally and be serialized to `null`.
#### Storage
Floating-point number values are stored directly inside a `basic_json` type.
*/
using number_float_t = NumberFloatType;
using number_float_t = NumberFloatType;
/// a type for list initialization
using list_init_t = std::initializer_list<basic_json>;
/// @}
/// @}
...
@@ -425,35 +708,6 @@ class basic_json
...
@@ -425,35 +708,6 @@ class basic_json
using parser_callback_t = std::function<bool(
using parser_callback_t = std::function<bool(
int depth, parse_event_t event, basic_json& parsed)>;
int depth, parse_event_t event, basic_json& parsed)>;
/*!
@brief comparison operator for JSON types
Returns an ordering that is similar to Python:
- order: null < boolean < number < object < array < string
- furthermore, each type is not smaller than itself
*/
friend bool operator<(const value_t lhs, const value_t rhs)
{
static constexpr std::array<uint8_t, 7> order = {{
0, // null
3, // object
4, // array
5, // string
1, // boolean
2, // integer
2 // float
}
};
// discarded values are not comparable
if (lhs == value_t::discarded or rhs == value_t::discarded)
{
return false;
}
return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
}
//////////////////
//////////////////
// constructors //
// constructors //
...
@@ -911,10 +1165,11 @@ class basic_json
...
@@ -911,10 +1165,11 @@ class basic_json
With the rules described above, the following JSON values cannot be
With the rules described above, the following JSON values cannot be
expressed by an initializer list:
expressed by an initializer list:
- the empty array (`[]`): use @ref array(list_init_t) with an empty
- the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
initializer list in this case
with an empty initializer list in this case
- arrays whose elements satisfy rule 2: use @ref array(list_init_t) with
- arrays whose elements satisfy rule 2: use @ref
the same initializer list in this case
array(std::initializer_list<basic_json>) with the same initializer list
in this case
@note When used without parentheses around an empty initializer list, @ref
@note When used without parentheses around an empty initializer list, @ref
basic_json() is called instead of this function, yielding the JSON null
basic_json() is called instead of this function, yielding the JSON null
...
@@ -925,7 +1180,8 @@ class basic_json
...
@@ -925,7 +1180,8 @@ class basic_json
@param[in] type_deduction internal parameter; when set to `true`, the type
@param[in] type_deduction internal parameter; when set to `true`, the type
of the JSON value is deducted from the initializer list @a init; when set
of the JSON value is deducted from the initializer list @a init; when set
to `false`, the type provided via @a manual_type is forced. This mode is
to `false`, the type provided via @a manual_type is forced. This mode is
used by the functions @ref array(list_init_t) and @ref object(list_init_t).
used by the functions @ref array(std::initializer_list<basic_json>) and
@ref object(std::initializer_list<basic_json>).
@param[in] manual_type internal parameter; when @a type_deduction is set to
@param[in] manual_type internal parameter; when @a type_deduction is set to
`false`, the created JSON value will use the provided type (only @ref
`false`, the created JSON value will use the provided type (only @ref
...
@@ -941,12 +1197,13 @@ class basic_json
...
@@ -941,12 +1197,13 @@ class basic_json
@liveexample{The example below shows how JSON values are created from
@liveexample{The example below shows how JSON values are created from
initializer lists,basic_json__list_init_t}
initializer lists,basic_json__list_init_t}
@sa basic_json array(
list_init_t) - create a JSON array value from an
@sa basic_json array(
std::initializer_list<basic_json>) - create a JSON
initializer list
array value from an
initializer list
@sa basic_json object(
list_init_t) - create a JSON object value from an
@sa basic_json object(
std::initializer_list<basic_json>) - create a JSON
initializer list
object value from an
initializer list
*/
*/
basic_json(list_init_t init, bool type_deduction = true,
basic_json(std::initializer_list<basic_json> init,
bool type_deduction = true,
value_t manual_type = value_t::array)
value_t manual_type = value_t::array)
{
{
// the initializer list could describe an object
// the initializer list could describe an object
...
@@ -1012,7 +1269,8 @@ class basic_json
...
@@ -1012,7 +1269,8 @@ class basic_json
@note This function is only needed to express two edge cases that cannot be
@note This function is only needed to express two edge cases that cannot be
realized with the initializer list constructor (@ref
realized with the initializer list constructor (@ref
basic_json(list_init_t, bool, value_t)). These cases are:
basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
are:
1. creating an array whose elements are all pairs whose first element is a
1. creating an array whose elements are all pairs whose first element is a
string - in this case, the initializer list constructor would create an
string - in this case, the initializer list constructor would create an
object, taking the first elements as keys
object, taking the first elements as keys
...
@@ -1029,12 +1287,13 @@ class basic_json
...
@@ -1029,12 +1287,13 @@ class basic_json
@liveexample{The following code shows an example for the @ref array
@liveexample{The following code shows an example for the @ref array
function.,array}
function.,array}
@sa basic_json(
list_init_t, bool, value_t) - create a JSON value from an
@sa basic_json(
std::initializer_list<basic_json>, bool, value_t) - create a
initializer list
JSON value from an
initializer list
@sa basic_json object(
list_init_t) - create a JSON object value from an
@sa basic_json object(
std::initializer_list<basic_json>) - create a JSON
initializer list
object value from an
initializer list
*/
*/
static basic_json array(list_init_t init = list_init_t())
static basic_json array(std::initializer_list<basic_json> init =
std::initializer_list<basic_json>())
{
{
return basic_json(init, false, value_t::array);
return basic_json(init, false, value_t::array);
}
}
...
@@ -1047,29 +1306,32 @@ class basic_json
...
@@ -1047,29 +1306,32 @@ class basic_json
the initializer list is empty, the empty object `{}` is created.
the initializer list is empty, the empty object `{}` is created.
@note This function is only added for symmetry reasons. In contrast to the
@note This function is only added for symmetry reasons. In contrast to the
related function @ref basic_json array(list_init_t), there are no cases
related function @ref basic_json array(std::initializer_list<basic_json>),
which can only be expressed by this function. That is, any initializer list
there are no cases which can only be expressed by this function. That is,
@a init can also be passed to the initializer list constructor @ref
any initializer list @a init can also be passed to the initializer list
basic_json(list_init_t, bool, value_t).
constructor @ref basic_json(std::initializer_list<basic_json>, bool,
value_t).
@param[in] init initializer list to create an object from (optional)
@param[in] init initializer list to create an object from (optional)
@return JSON object value
@return JSON object value
@throw std::domain_error if @a init is not a pair whose first elements are
@throw std::domain_error if @a init is not a pair whose first elements are
strings; thrown by @ref basic_json(list_init_t, bool, value_t)
strings; thrown by @ref basic_json(std::initializer_list<basic_json>, bool,
value_t)
@complexity Linear in the size of @a init.
@complexity Linear in the size of @a init.
@liveexample{The following code shows an example for the @ref object
@liveexample{The following code shows an example for the @ref object
function.,object}
function.,object}
@sa basic_json(
list_init_t, bool, value_t) - create a JSON value from an
@sa basic_json(
std::initializer_list<basic_json>, bool, value_t) - create a
initializer list
JSON value from an
initializer list
@sa basic_json array(
list_init_t) - create a JSON array value from an
@sa basic_json array(
std::initializer_list<basic_json>) - create a JSON
initializer list
array value from an
initializer list
*/
*/
static basic_json object(list_init_t init = list_init_t())
static basic_json object(std::initializer_list<basic_json> init =
std::initializer_list<basic_json>())
{
{
return basic_json(init, false, value_t::object);
return basic_json(init, false, value_t::object);
}
}
...
@@ -3592,6 +3854,37 @@ class basic_json
...
@@ -3592,6 +3854,37 @@ class basic_json
/// @name lexicographical comparison operators
/// @name lexicographical comparison operators
/// @{
/// @{
private:
/*!
@brief comparison operator for JSON types
Returns an ordering that is similar to Python:
- order: null < boolean < number < object < array < string
- furthermore, each type is not smaller than itself
*/
friend bool operator<(const value_t lhs, const value_t rhs)
{
static constexpr std::array<uint8_t, 7> order = {{
0, // null
3, // object
4, // array
5, // string
1, // boolean
2, // integer
2 // float
}
};
// discarded values are not comparable
if (lhs == value_t::discarded or rhs == value_t::discarded)
{
return false;
}
return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
}
public:
/*!
/*!
@brief comparison: equal
@brief comparison: equal
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment