more documentation
In this commit, also the semantics for values skipped via the parser callback has changed. Now, the top-level value is returned as “null” instead of “discarded”.
This commit is contained in:
parent
48545f5b18
commit
457572184c
25 changed files with 856 additions and 60 deletions
|
@ -163,7 +163,7 @@ CHM_FILE =
|
|||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = YES
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
|
@ -176,7 +176,7 @@ QHG_LOCATION =
|
|||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
|
|
@ -56,8 +56,6 @@ docset: create_output
|
|||
cp Doxyfile Doxyfile_docset
|
||||
gsed -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset
|
||||
gsed -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset
|
||||
gsed -i 's/GENERATE_TREEVIEW = YES/GENERATE_TREEVIEW = NO/' Doxyfile_docset
|
||||
gsed -i 's/BINARY_TOC = YES/BINARY_TOC = NO/' Doxyfile_docset
|
||||
gsed -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset
|
||||
rm -fr html *.docset
|
||||
doxygen Doxyfile_docset
|
||||
|
|
33
doc/examples/at__object_t_key_type.cpp
Normal file
33
doc/examples/at__object_t_key_type.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create JSON object
|
||||
json object =
|
||||
{
|
||||
{"the good", "il buono"},
|
||||
{"the bad", "il cativo"},
|
||||
{"the ugly", "il brutto"}
|
||||
};
|
||||
|
||||
// output element with key "the ugly"
|
||||
std::cout << object.at("the ugly") << '\n';
|
||||
|
||||
// change element with key "the bad"
|
||||
object.at("the bad") = "il cattivo";
|
||||
|
||||
// output changed array
|
||||
std::cout << object << '\n';
|
||||
|
||||
// try to write at a nonexisting key
|
||||
try
|
||||
{
|
||||
object.at("the fast") = "il rapido";
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
std::cout << "out of range" << '\n';
|
||||
}
|
||||
}
|
3
doc/examples/at__object_t_key_type.output
Normal file
3
doc/examples/at__object_t_key_type.output
Normal file
|
@ -0,0 +1,3 @@
|
|||
"il brutto"
|
||||
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
|
||||
out of range
|
27
doc/examples/at__object_t_key_type_const.cpp
Normal file
27
doc/examples/at__object_t_key_type_const.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create JSON object
|
||||
json object =
|
||||
{
|
||||
{"the good", "il buono"},
|
||||
{"the bad", "il cativo"},
|
||||
{"the ugly", "il brutto"}
|
||||
};
|
||||
|
||||
// output element with key "the ugly"
|
||||
std::cout << object.at("the ugly") << '\n';
|
||||
|
||||
// try to read from a nonexisting key
|
||||
try
|
||||
{
|
||||
std::cout << object.at("the fast") << '\n';
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
std::cout << "out of range" << '\n';
|
||||
}
|
||||
}
|
2
doc/examples/at__object_t_key_type_const.output
Normal file
2
doc/examples/at__object_t_key_type_const.output
Normal file
|
@ -0,0 +1,2 @@
|
|||
"il brutto"
|
||||
out of range
|
28
doc/examples/at__size_type.cpp
Normal file
28
doc/examples/at__size_type.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create JSON array
|
||||
json array = {"first", "2nd", "third", "fourth"};
|
||||
|
||||
// output element at index 2 (third element)
|
||||
std::cout << array.at(2) << '\n';
|
||||
|
||||
// change element at index 1 (second element) to "second"
|
||||
array.at(1) = "second";
|
||||
|
||||
// output changed array
|
||||
std::cout << array << '\n';
|
||||
|
||||
// try to write beyond the array limit
|
||||
try
|
||||
{
|
||||
array.at(5) = "sixth";
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
std::cout << "out of range" << '\n';
|
||||
}
|
||||
}
|
3
doc/examples/at__size_type.output
Normal file
3
doc/examples/at__size_type.output
Normal file
|
@ -0,0 +1,3 @@
|
|||
"third"
|
||||
["first","second","third","fourth"]
|
||||
out of range
|
22
doc/examples/at__size_type_const.cpp
Normal file
22
doc/examples/at__size_type_const.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create JSON array
|
||||
json array = {"first", "2nd", "third", "fourth"};
|
||||
|
||||
// output element at index 2 (third element)
|
||||
std::cout << array.at(2) << '\n';
|
||||
|
||||
// try to read beyond the array limit
|
||||
try
|
||||
{
|
||||
std::cout << array.at(5) << '\n';
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
std::cout << "out of range" << '\n';
|
||||
}
|
||||
}
|
2
doc/examples/at__size_type_const.output
Normal file
2
doc/examples/at__size_type_const.output
Normal file
|
@ -0,0 +1,2 @@
|
|||
"third"
|
||||
out of range
|
24
doc/examples/operatorarray__size_type.cpp
Normal file
24
doc/examples/operatorarray__size_type.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create a JSON array
|
||||
json array = {1, 2, 3, 4, 5};
|
||||
|
||||
// output element at index 3 (fourth element)
|
||||
std::cout << array[3] << '\n';
|
||||
|
||||
// change last element to 6
|
||||
array[array.size() - 1] = 6;
|
||||
|
||||
// output changed array
|
||||
std::cout << array << '\n';
|
||||
|
||||
// write beyond array limit
|
||||
array[10] = 11;
|
||||
|
||||
// output changed array
|
||||
std::cout << array << '\n';
|
||||
}
|
3
doc/examples/operatorarray__size_type.output
Normal file
3
doc/examples/operatorarray__size_type.output
Normal file
|
@ -0,0 +1,3 @@
|
|||
4
|
||||
[1,2,3,4,6]
|
||||
[1,2,3,4,6,null,null,null,null,null,11]
|
12
doc/examples/operatorarray__size_type_const.cpp
Normal file
12
doc/examples/operatorarray__size_type_const.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create JSON array
|
||||
json array = {"first", "2nd", "third", "fourth"};
|
||||
|
||||
// output element at index 2 (third element)
|
||||
std::cout << array.at(2) << '\n';
|
||||
}
|
1
doc/examples/operatorarray__size_type_const.output
Normal file
1
doc/examples/operatorarray__size_type_const.output
Normal file
|
@ -0,0 +1 @@
|
|||
"third"
|
55
doc/examples/parse__istream__parser_callback_t.cpp
Normal file
55
doc/examples/parse__istream__parser_callback_t.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
auto text = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": 100
|
||||
},
|
||||
"Animated" : false,
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
// fill a stream with JSON text
|
||||
std::stringstream ss;
|
||||
ss << text;
|
||||
|
||||
// parse and serialize JSON
|
||||
json j_complete = json::parse(ss);
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
|
||||
|
||||
// define parser callback
|
||||
json::parser_callback_t cb = [](int depth, json::parse_event_t event, json & parsed)
|
||||
{
|
||||
// skip object elements with key "Thumbnail"
|
||||
if (event == json::parse_event_t::key and parsed == json("Thumbnail"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// fill a stream with JSON text
|
||||
ss.clear();
|
||||
ss << text;
|
||||
|
||||
// parse (with callback) and serialize JSON
|
||||
json j_filtered = json::parse(ss, cb);
|
||||
std::cout << std::setw(4) << j_filtered << '\n';
|
||||
}
|
34
doc/examples/parse__istream__parser_callback_t.output
Normal file
34
doc/examples/parse__istream__parser_callback_t.output
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"Image": {
|
||||
"Animated": false,
|
||||
"Height": 600,
|
||||
"IDs": [
|
||||
116,
|
||||
943,
|
||||
234,
|
||||
38793
|
||||
],
|
||||
"Thumbnail": {
|
||||
"Height": 125,
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Width": 100
|
||||
},
|
||||
"Title": "View from 15th Floor",
|
||||
"Width": 800
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"Image": {
|
||||
"Animated": false,
|
||||
"Height": 600,
|
||||
"IDs": [
|
||||
116,
|
||||
943,
|
||||
234,
|
||||
38793
|
||||
],
|
||||
"Title": "View from 15th Floor",
|
||||
"Width": 800
|
||||
}
|
||||
}
|
47
doc/examples/parse__string__parser_callback_t.cpp
Normal file
47
doc/examples/parse__string__parser_callback_t.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
std::string text = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": 100
|
||||
},
|
||||
"Animated" : false,
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
// parse and serialize JSON
|
||||
json j_complete = json::parse(text);
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
|
||||
|
||||
// define parser callback
|
||||
json::parser_callback_t cb = [](int depth, json::parse_event_t event, json & parsed)
|
||||
{
|
||||
// skip object elements with key "Thumbnail"
|
||||
if (event == json::parse_event_t::key and parsed == json("Thumbnail"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// parse (with callback) and serialize JSON
|
||||
json j_filtered = json::parse(text, cb);
|
||||
std::cout << std::setw(4) << j_filtered << '\n';
|
||||
}
|
34
doc/examples/parse__string__parser_callback_t.output
Normal file
34
doc/examples/parse__string__parser_callback_t.output
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"Image": {
|
||||
"Animated": false,
|
||||
"Height": 600,
|
||||
"IDs": [
|
||||
116,
|
||||
943,
|
||||
234,
|
||||
38793
|
||||
],
|
||||
"Thumbnail": {
|
||||
"Height": 125,
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Width": 100
|
||||
},
|
||||
"Title": "View from 15th Floor",
|
||||
"Width": 800
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"Image": {
|
||||
"Animated": false,
|
||||
"Height": 600,
|
||||
"IDs": [
|
||||
116,
|
||||
943,
|
||||
234,
|
||||
38793
|
||||
],
|
||||
"Title": "View from 15th Floor",
|
||||
"Width": 800
|
||||
}
|
||||
}
|
19
doc/examples/swap__array_t.cpp
Normal file
19
doc/examples/swap__array_t.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create a JSON value
|
||||
json value = {{"array", {1, 2, 3, 4}}};
|
||||
|
||||
// create an array_t
|
||||
json::array_t array = {"Snap", "Crackle", "Pop"};
|
||||
|
||||
// swap the array stored in the JSON value
|
||||
value["array"].swap(array);
|
||||
|
||||
// output the values
|
||||
std::cout << "value = " << value << '\n';
|
||||
std::cout << "array = " << array << '\n';
|
||||
}
|
2
doc/examples/swap__array_t.output
Normal file
2
doc/examples/swap__array_t.output
Normal file
|
@ -0,0 +1,2 @@
|
|||
value = {"array":["Snap","Crackle","Pop"]}
|
||||
array = [1,2,3,4]
|
17
doc/examples/swap__reference.cpp
Normal file
17
doc/examples/swap__reference.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create two JSON values
|
||||
json j1 = {1, 2, 3, 4, 5};
|
||||
json j2 = {{"pi", 3.141592653589793}, {"e", 2.718281828459045}};
|
||||
|
||||
// swap the values
|
||||
j1.swap(j2);
|
||||
|
||||
// output the values
|
||||
std::cout << "j1 = " << j1 << '\n';
|
||||
std::cout << "j2 = " << j2 << '\n';
|
||||
}
|
2
doc/examples/swap__reference.output
Normal file
2
doc/examples/swap__reference.output
Normal file
|
@ -0,0 +1,2 @@
|
|||
j1 = {"e":2.71828182845905,"pi":3.14159265358979}
|
||||
j2 = [1,2,3,4,5]
|
260
src/json.hpp
260
src/json.hpp
|
@ -336,20 +336,77 @@ class basic_json
|
|||
// JSON parser callback //
|
||||
//////////////////////////
|
||||
|
||||
/// JSON callback event enumeration
|
||||
/*!
|
||||
@brief JSON callback events
|
||||
|
||||
This enumeration lists the parser events that can trigger calling a
|
||||
callback function of type @ref parser_callback_t during parsing.
|
||||
*/
|
||||
enum class parse_event_t : uint8_t
|
||||
{
|
||||
object_start, ///< start an object scope (found a '{' token)
|
||||
object_end, ///< end of an object scope (found '}' token)
|
||||
array_start, ///< start of an array scope (found '[' token)
|
||||
array_end, ///< end of an array scope (found ']' token)
|
||||
key, ///< found an object key within an object scope
|
||||
value ///< a value in an appropriate context (i.e., following a tag in an object scope)
|
||||
/// the parser read `{` and started to process a JSON object
|
||||
object_start,
|
||||
/// the parser read `}` and finished processing a JSON object
|
||||
object_end,
|
||||
/// the parser read `[` and started to process a JSON array
|
||||
array_start,
|
||||
/// the parser read `]` and finished processing a JSON array
|
||||
array_end,
|
||||
/// the parser read a key of a value in an object
|
||||
key,
|
||||
/// the parser finished reading a JSON value
|
||||
value
|
||||
};
|
||||
|
||||
/// per-element parser callback type
|
||||
using parser_callback_t = std::function<bool(int depth, parse_event_t event,
|
||||
const basic_json& parsed)>;
|
||||
/*!
|
||||
@brief per-element parser callback type
|
||||
|
||||
With a parser callback function, the result of parsing a JSON text can be
|
||||
influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
|
||||
@ref parse(const string_t&, parser_callback_t), it is called on certain
|
||||
events (passed as @ref parse_event_t via parameter @a event) with a set
|
||||
recursion depth @a depth and context JSON value @a parsed. The return value
|
||||
of the callback function is a boolean indicating whether the element that
|
||||
emitted the callback shall be kept or not.
|
||||
|
||||
We distinguish six scenarios (determined by the event type) in which the
|
||||
callback function can be called. The following table describes the values
|
||||
of the parameters @a depth, @a event, and @a parsed.
|
||||
|
||||
parameter @a event | description | parameter @a depth | parameter @a parsed
|
||||
------------------ | ----------- | ------------------ | -------------------
|
||||
parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
|
||||
parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
|
||||
parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
|
||||
parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
|
||||
parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
|
||||
parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
|
||||
|
||||
Discarding a value (i.e., returning `false`) has different effects depending on the
|
||||
context in which function was called:
|
||||
|
||||
- Discarded values in structured types are skipped. That is, the parser
|
||||
will behave as if the discarded value was never read.
|
||||
- In case a value outside a structured type is skipped, it is replaced with
|
||||
`null`. This case happens if the top-level element is skipped.
|
||||
|
||||
@param[in] depth the depth of the recursion during parsing
|
||||
|
||||
@param[in] event an event of type parse_event_t indicating the context in
|
||||
the callback function has been called
|
||||
|
||||
@param[in,out] parsed the current intermediate parse result; note that
|
||||
writing to this value has no effect for parse_event_t::key events
|
||||
|
||||
@return Whether the JSON value which called the function during parsing
|
||||
should be kept (`true`) or not (`false`). In the latter case, it is either
|
||||
skipped completely or replaced by an empty discarded object.
|
||||
|
||||
@sa @ref parse(std::istream&, parser_callback_t) or
|
||||
@ref parse(const string_t&, parser_callback_t) for examples
|
||||
*/
|
||||
using parser_callback_t = std::function<bool(
|
||||
int depth, parse_event_t event, basic_json& parsed)>;
|
||||
|
||||
/*!
|
||||
@brief comparison operator for JSON value types
|
||||
|
@ -1760,7 +1817,25 @@ class basic_json
|
|||
/// @name element access
|
||||
/// @{
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified array element with bounds checking
|
||||
|
||||
Returns a reference to the element at specified location @a idx, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
@throw std::out_of_range if the index @a idx is out of range of the array;
|
||||
that is, `idx >= size()`
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read and
|
||||
written using at.,at__size_type}
|
||||
*/
|
||||
reference at(size_type idx)
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -1772,7 +1847,25 @@ class basic_json
|
|||
return m_value.array->at(idx);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified array element with bounds checking
|
||||
|
||||
Returns a const reference to the element at specified location @a idx, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return const reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
@throw std::out_of_range if the index @a idx is out of range of the array;
|
||||
that is, `idx >= size()`
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read using
|
||||
at.,at__size_type_const}
|
||||
*/
|
||||
const_reference at(size_type idx) const
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -1784,7 +1877,25 @@ class basic_json
|
|||
return m_value.array->at(idx);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified object element with bounds checking
|
||||
|
||||
Returns a reference to the element at with specified key @a key, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object
|
||||
@throw std::out_of_range if the key @a key is is not stored in the object;
|
||||
that is, `find(key) == end()`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read and
|
||||
written using at.,at__object_t_key_type}
|
||||
*/
|
||||
reference at(const typename object_t::key_type& key)
|
||||
{
|
||||
// at only works for objects
|
||||
|
@ -1796,7 +1907,25 @@ class basic_json
|
|||
return m_value.object->at(key);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified object element with bounds checking
|
||||
|
||||
Returns a const reference to the element at with specified key @a key, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return const reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object
|
||||
@throw std::out_of_range if the key @a key is is not stored in the object;
|
||||
that is, `find(key) == end()`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read using
|
||||
at.,at__object_t_key_type_const}
|
||||
*/
|
||||
const_reference at(const typename object_t::key_type& key) const
|
||||
{
|
||||
// at only works for objects
|
||||
|
@ -1808,7 +1937,28 @@ class basic_json
|
|||
return m_value.object->at(key);
|
||||
}
|
||||
|
||||
/// access specified element
|
||||
/*!
|
||||
@brief access specified array element
|
||||
|
||||
Returns a reference to the element at specified location @a idx.
|
||||
|
||||
@note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
|
||||
then the array is silently filled up with `null` values to make `idx` a
|
||||
valid reference to the last stored element.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array or null
|
||||
|
||||
@complexity Constant if @a idx is in the range of the array. Otherwise
|
||||
linear in `idx - size()`.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read and
|
||||
written using [] operator. Note the addition of `null`
|
||||
values.,operatorarray__size_type}
|
||||
*/
|
||||
reference operator[](size_type idx)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
|
@ -1834,7 +1984,22 @@ class basic_json
|
|||
return m_value.array->operator[](idx);
|
||||
}
|
||||
|
||||
/// access specified element
|
||||
/*!
|
||||
@brief access specified array element
|
||||
|
||||
Returns a const reference to the element at specified location @a idx.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return const reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read using
|
||||
the [] operator.,operatorarray__size_type_const}
|
||||
*/
|
||||
const_reference operator[](size_type idx) const
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -2750,6 +2915,19 @@ class basic_json
|
|||
|
||||
/*!
|
||||
@brief exchanges the values
|
||||
|
||||
Exchanges the contents of the JSON value with those of @a other. Does not
|
||||
invoke any move, copy, or swap operations on individual elements. All
|
||||
iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated.
|
||||
|
||||
@param[in,out] other JSON value to exchange the contents with
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how JSON arrays can be
|
||||
swapped.,swap__reference}
|
||||
|
||||
@ingroup container
|
||||
*/
|
||||
void swap(reference other) noexcept (
|
||||
|
@ -2763,7 +2941,25 @@ class basic_json
|
|||
std::swap(m_value, other.m_value);
|
||||
}
|
||||
|
||||
/// swaps the contents
|
||||
/*!
|
||||
@brief exchanges the values
|
||||
|
||||
Exchanges the contents of a JSON array with those of @a other. Does not
|
||||
invoke any move, copy, or swap operations on individual elements. All
|
||||
iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated.
|
||||
|
||||
@param[in,out] other array to exchange the contents with
|
||||
|
||||
@throw std::domain_error when JSON value is not an array
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how JSON values can be
|
||||
swapped.,swap__array_t}
|
||||
|
||||
@ingroup container
|
||||
*/
|
||||
void swap(array_t& other)
|
||||
{
|
||||
// swap only works for arrays
|
||||
|
@ -3082,8 +3278,9 @@ class basic_json
|
|||
@brief deserialize from string
|
||||
|
||||
@param[in] s string to read a serialized JSON value from
|
||||
@param[in] cb a parser callback function of type parser_callback_t which is
|
||||
used to control the deserialization by filtering unwanted values (optional)
|
||||
@param[in] cb a parser callback function of type @ref parser_callback_t
|
||||
which is used to control the deserialization by filtering unwanted values
|
||||
(optional)
|
||||
|
||||
@return result of the deserialization
|
||||
|
||||
|
@ -3091,7 +3288,8 @@ class basic_json
|
|||
LL(1) parser. The complexity can be higher if the parser callback function
|
||||
@a cb has a super-linear complexity.
|
||||
|
||||
@todo Add example.
|
||||
@liveexample{The example below demonstrates the parse function with and
|
||||
without callback function.,parse__string__parser_callback_t}
|
||||
|
||||
@sa parse(std::istream&, parser_callback_t) for a version that reads from
|
||||
an input stream
|
||||
|
@ -3105,8 +3303,9 @@ class basic_json
|
|||
@brief deserialize from stream
|
||||
|
||||
@param[in,out] i stream to read a serialized JSON value from
|
||||
@param[in] cb a parser callback function of type parser_callback_t which is
|
||||
used to control the deserialization by filtering unwanted values (optional)
|
||||
@param[in] cb a parser callback function of type @ref parser_callback_t
|
||||
which is used to control the deserialization by filtering unwanted values
|
||||
(optional)
|
||||
|
||||
@return result of the deserialization
|
||||
|
||||
|
@ -3114,7 +3313,8 @@ class basic_json
|
|||
LL(1) parser. The complexity can be higher if the parser callback function
|
||||
@a cb has a super-linear complexity.
|
||||
|
||||
@todo Add example.
|
||||
@liveexample{The example below demonstrates the parse function with and
|
||||
without callback function.,parse__istream__parser_callback_t}
|
||||
|
||||
@sa parse(const string_t&, parser_callback_t) for a version that reads
|
||||
from a string
|
||||
|
@ -5710,7 +5910,9 @@ basic_json_parser_59:
|
|||
|
||||
expect(lexer::token_type::end_of_input);
|
||||
|
||||
return result;
|
||||
// return parser result and replace it with null in case the
|
||||
// top-level value was discarded by the callback function
|
||||
return result.is_discarded() ? basic_json() : result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -5763,7 +5965,15 @@ basic_json_parser_59:
|
|||
bool keep_tag = false;
|
||||
if (keep)
|
||||
{
|
||||
keep_tag = callback ? callback(depth, parse_event_t::key, basic_json(key)) : true;
|
||||
if (callback)
|
||||
{
|
||||
basic_json k(key);
|
||||
keep_tag = callback(depth, parse_event_t::key, k);
|
||||
}
|
||||
else
|
||||
{
|
||||
keep_tag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// parse separator (:)
|
||||
|
|
|
@ -336,20 +336,77 @@ class basic_json
|
|||
// JSON parser callback //
|
||||
//////////////////////////
|
||||
|
||||
/// JSON callback event enumeration
|
||||
/*!
|
||||
@brief JSON callback events
|
||||
|
||||
This enumeration lists the parser events that can trigger calling a
|
||||
callback function of type @ref parser_callback_t during parsing.
|
||||
*/
|
||||
enum class parse_event_t : uint8_t
|
||||
{
|
||||
object_start, ///< start an object scope (found a '{' token)
|
||||
object_end, ///< end of an object scope (found '}' token)
|
||||
array_start, ///< start of an array scope (found '[' token)
|
||||
array_end, ///< end of an array scope (found ']' token)
|
||||
key, ///< found an object key within an object scope
|
||||
value ///< a value in an appropriate context (i.e., following a tag in an object scope)
|
||||
/// the parser read `{` and started to process a JSON object
|
||||
object_start,
|
||||
/// the parser read `}` and finished processing a JSON object
|
||||
object_end,
|
||||
/// the parser read `[` and started to process a JSON array
|
||||
array_start,
|
||||
/// the parser read `]` and finished processing a JSON array
|
||||
array_end,
|
||||
/// the parser read a key of a value in an object
|
||||
key,
|
||||
/// the parser finished reading a JSON value
|
||||
value
|
||||
};
|
||||
|
||||
/// per-element parser callback type
|
||||
using parser_callback_t = std::function<bool(int depth, parse_event_t event,
|
||||
const basic_json& parsed)>;
|
||||
/*!
|
||||
@brief per-element parser callback type
|
||||
|
||||
With a parser callback function, the result of parsing a JSON text can be
|
||||
influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
|
||||
@ref parse(const string_t&, parser_callback_t), it is called on certain
|
||||
events (passed as @ref parse_event_t via parameter @a event) with a set
|
||||
recursion depth @a depth and context JSON value @a parsed. The return value
|
||||
of the callback function is a boolean indicating whether the element that
|
||||
emitted the callback shall be kept or not.
|
||||
|
||||
We distinguish six scenarios (determined by the event type) in which the
|
||||
callback function can be called. The following table describes the values
|
||||
of the parameters @a depth, @a event, and @a parsed.
|
||||
|
||||
parameter @a event | description | parameter @a depth | parameter @a parsed
|
||||
------------------ | ----------- | ------------------ | -------------------
|
||||
parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
|
||||
parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
|
||||
parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
|
||||
parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
|
||||
parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
|
||||
parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
|
||||
|
||||
Discarding a value (i.e., returning `false`) has different effects depending on the
|
||||
context in which function was called:
|
||||
|
||||
- Discarded values in structured types are skipped. That is, the parser
|
||||
will behave as if the discarded value was never read.
|
||||
- In case a value outside a structured type is skipped, it is replaced with
|
||||
`null`. This case happens if the top-level element is skipped.
|
||||
|
||||
@param[in] depth the depth of the recursion during parsing
|
||||
|
||||
@param[in] event an event of type parse_event_t indicating the context in
|
||||
the callback function has been called
|
||||
|
||||
@param[in,out] parsed the current intermediate parse result; note that
|
||||
writing to this value has no effect for parse_event_t::key events
|
||||
|
||||
@return Whether the JSON value which called the function during parsing
|
||||
should be kept (`true`) or not (`false`). In the latter case, it is either
|
||||
skipped completely or replaced by an empty discarded object.
|
||||
|
||||
@sa @ref parse(std::istream&, parser_callback_t) or
|
||||
@ref parse(const string_t&, parser_callback_t) for examples
|
||||
*/
|
||||
using parser_callback_t = std::function<bool(
|
||||
int depth, parse_event_t event, basic_json& parsed)>;
|
||||
|
||||
/*!
|
||||
@brief comparison operator for JSON value types
|
||||
|
@ -1760,7 +1817,25 @@ class basic_json
|
|||
/// @name element access
|
||||
/// @{
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified array element with bounds checking
|
||||
|
||||
Returns a reference to the element at specified location @a idx, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
@throw std::out_of_range if the index @a idx is out of range of the array;
|
||||
that is, `idx >= size()`
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read and
|
||||
written using at.,at__size_type}
|
||||
*/
|
||||
reference at(size_type idx)
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -1772,7 +1847,25 @@ class basic_json
|
|||
return m_value.array->at(idx);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified array element with bounds checking
|
||||
|
||||
Returns a const reference to the element at specified location @a idx, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return const reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
@throw std::out_of_range if the index @a idx is out of range of the array;
|
||||
that is, `idx >= size()`
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read using
|
||||
at.,at__size_type_const}
|
||||
*/
|
||||
const_reference at(size_type idx) const
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -1784,7 +1877,25 @@ class basic_json
|
|||
return m_value.array->at(idx);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified object element with bounds checking
|
||||
|
||||
Returns a reference to the element at with specified key @a key, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object
|
||||
@throw std::out_of_range if the key @a key is is not stored in the object;
|
||||
that is, `find(key) == end()`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read and
|
||||
written using at.,at__object_t_key_type}
|
||||
*/
|
||||
reference at(const typename object_t::key_type& key)
|
||||
{
|
||||
// at only works for objects
|
||||
|
@ -1796,7 +1907,25 @@ class basic_json
|
|||
return m_value.object->at(key);
|
||||
}
|
||||
|
||||
/// access specified element with bounds checking
|
||||
/*!
|
||||
@brief access specified object element with bounds checking
|
||||
|
||||
Returns a const reference to the element at with specified key @a key, with
|
||||
bounds checking.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return const reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object
|
||||
@throw std::out_of_range if the key @a key is is not stored in the object;
|
||||
that is, `find(key) == end()`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read using
|
||||
at.,at__object_t_key_type_const}
|
||||
*/
|
||||
const_reference at(const typename object_t::key_type& key) const
|
||||
{
|
||||
// at only works for objects
|
||||
|
@ -1808,7 +1937,28 @@ class basic_json
|
|||
return m_value.object->at(key);
|
||||
}
|
||||
|
||||
/// access specified element
|
||||
/*!
|
||||
@brief access specified array element
|
||||
|
||||
Returns a reference to the element at specified location @a idx.
|
||||
|
||||
@note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
|
||||
then the array is silently filled up with `null` values to make `idx` a
|
||||
valid reference to the last stored element.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array or null
|
||||
|
||||
@complexity Constant if @a idx is in the range of the array. Otherwise
|
||||
linear in `idx - size()`.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read and
|
||||
written using [] operator. Note the addition of `null`
|
||||
values.,operatorarray__size_type}
|
||||
*/
|
||||
reference operator[](size_type idx)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
|
@ -1834,7 +1984,22 @@ class basic_json
|
|||
return m_value.array->operator[](idx);
|
||||
}
|
||||
|
||||
/// access specified element
|
||||
/*!
|
||||
@brief access specified array element
|
||||
|
||||
Returns a const reference to the element at specified location @a idx.
|
||||
|
||||
@param[in] idx index of the element to access
|
||||
|
||||
@return const reference to the element at index @a idx
|
||||
|
||||
@throw std::domain_error if JSON is not an array
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how array elements can be read using
|
||||
the [] operator.,operatorarray__size_type_const}
|
||||
*/
|
||||
const_reference operator[](size_type idx) const
|
||||
{
|
||||
// at only works for arrays
|
||||
|
@ -2750,6 +2915,19 @@ class basic_json
|
|||
|
||||
/*!
|
||||
@brief exchanges the values
|
||||
|
||||
Exchanges the contents of the JSON value with those of @a other. Does not
|
||||
invoke any move, copy, or swap operations on individual elements. All
|
||||
iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated.
|
||||
|
||||
@param[in,out] other JSON value to exchange the contents with
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how JSON arrays can be
|
||||
swapped.,swap__reference}
|
||||
|
||||
@ingroup container
|
||||
*/
|
||||
void swap(reference other) noexcept (
|
||||
|
@ -2763,7 +2941,25 @@ class basic_json
|
|||
std::swap(m_value, other.m_value);
|
||||
}
|
||||
|
||||
/// swaps the contents
|
||||
/*!
|
||||
@brief exchanges the values
|
||||
|
||||
Exchanges the contents of a JSON array with those of @a other. Does not
|
||||
invoke any move, copy, or swap operations on individual elements. All
|
||||
iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated.
|
||||
|
||||
@param[in,out] other array to exchange the contents with
|
||||
|
||||
@throw std::domain_error when JSON value is not an array
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how JSON values can be
|
||||
swapped.,swap__array_t}
|
||||
|
||||
@ingroup container
|
||||
*/
|
||||
void swap(array_t& other)
|
||||
{
|
||||
// swap only works for arrays
|
||||
|
@ -3082,8 +3278,9 @@ class basic_json
|
|||
@brief deserialize from string
|
||||
|
||||
@param[in] s string to read a serialized JSON value from
|
||||
@param[in] cb a parser callback function of type parser_callback_t which is
|
||||
used to control the deserialization by filtering unwanted values (optional)
|
||||
@param[in] cb a parser callback function of type @ref parser_callback_t
|
||||
which is used to control the deserialization by filtering unwanted values
|
||||
(optional)
|
||||
|
||||
@return result of the deserialization
|
||||
|
||||
|
@ -3091,7 +3288,8 @@ class basic_json
|
|||
LL(1) parser. The complexity can be higher if the parser callback function
|
||||
@a cb has a super-linear complexity.
|
||||
|
||||
@todo Add example.
|
||||
@liveexample{The example below demonstrates the parse function with and
|
||||
without callback function.,parse__string__parser_callback_t}
|
||||
|
||||
@sa parse(std::istream&, parser_callback_t) for a version that reads from
|
||||
an input stream
|
||||
|
@ -3105,8 +3303,9 @@ class basic_json
|
|||
@brief deserialize from stream
|
||||
|
||||
@param[in,out] i stream to read a serialized JSON value from
|
||||
@param[in] cb a parser callback function of type parser_callback_t which is
|
||||
used to control the deserialization by filtering unwanted values (optional)
|
||||
@param[in] cb a parser callback function of type @ref parser_callback_t
|
||||
which is used to control the deserialization by filtering unwanted values
|
||||
(optional)
|
||||
|
||||
@return result of the deserialization
|
||||
|
||||
|
@ -3114,7 +3313,8 @@ class basic_json
|
|||
LL(1) parser. The complexity can be higher if the parser callback function
|
||||
@a cb has a super-linear complexity.
|
||||
|
||||
@todo Add example.
|
||||
@liveexample{The example below demonstrates the parse function with and
|
||||
without callback function.,parse__istream__parser_callback_t}
|
||||
|
||||
@sa parse(const string_t&, parser_callback_t) for a version that reads
|
||||
from a string
|
||||
|
@ -5016,7 +5216,9 @@ class basic_json
|
|||
|
||||
expect(lexer::token_type::end_of_input);
|
||||
|
||||
return result;
|
||||
// return parser result and replace it with null in case the
|
||||
// top-level value was discarded by the callback function
|
||||
return result.is_discarded() ? basic_json() : result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -5069,7 +5271,15 @@ class basic_json
|
|||
bool keep_tag = false;
|
||||
if (keep)
|
||||
{
|
||||
keep_tag = callback ? callback(depth, parse_event_t::key, basic_json(key)) : true;
|
||||
if (callback)
|
||||
{
|
||||
basic_json k(key);
|
||||
keep_tag = callback(depth, parse_event_t::key, k);
|
||||
}
|
||||
else
|
||||
{
|
||||
keep_tag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// parse separator (:)
|
||||
|
|
|
@ -7742,14 +7742,16 @@ TEST_CASE("parser class")
|
|||
return false;
|
||||
});
|
||||
|
||||
CHECK (j_object.is_discarded());
|
||||
// the top-level object will be discarded, leaving a null
|
||||
CHECK (j_object.is_null());
|
||||
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
|
||||
{
|
||||
return false;
|
||||
});
|
||||
|
||||
CHECK (j_array.is_discarded());
|
||||
// the top-level array will be discarded, leaving a null
|
||||
CHECK (j_array.is_null());
|
||||
}
|
||||
|
||||
SECTION("filter specific element")
|
||||
|
@ -7791,8 +7793,10 @@ TEST_CASE("parser class")
|
|||
{
|
||||
json j_object = json::parse(s_object, [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
if (e == json::parse_event_t::object_end)
|
||||
static bool first = true;
|
||||
if (e == json::parse_event_t::object_end and first)
|
||||
{
|
||||
first = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -7801,14 +7805,17 @@ TEST_CASE("parser class")
|
|||
}
|
||||
});
|
||||
|
||||
CHECK (j_object.is_discarded());
|
||||
// the first completed object will be discarded
|
||||
CHECK (j_object == json({{"foo", 2}}));
|
||||
}
|
||||
|
||||
{
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
if (e == json::parse_event_t::array_end)
|
||||
static bool first = true;
|
||||
if (e == json::parse_event_t::array_end and first)
|
||||
{
|
||||
first = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -7817,7 +7824,8 @@ TEST_CASE("parser class")
|
|||
}
|
||||
});
|
||||
|
||||
CHECK (j_array.is_discarded());
|
||||
// the first completed array will be discarded
|
||||
CHECK (j_array == json({1, 2, 4, 5}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue