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”.
pull/75/merge
Niels 2015-06-24 12:15:51 +02:00
parent 48545f5b18
commit 457572184c
25 changed files with 856 additions and 60 deletions

View File

@ -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

View File

@ -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

View 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';
}
}

View File

@ -0,0 +1,3 @@
"il brutto"
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
out of range

View 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';
}
}

View File

@ -0,0 +1,2 @@
"il brutto"
out of range

View 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';
}
}

View File

@ -0,0 +1,3 @@
"third"
["first","second","third","fourth"]
out of range

View 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';
}
}

View File

@ -0,0 +1,2 @@
"third"
out of range

View 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';
}

View File

@ -0,0 +1,3 @@
4
[1,2,3,4,6]
[1,2,3,4,6,null,null,null,null,null,11]

View 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';
}

View File

@ -0,0 +1 @@
"third"

View 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';
}

View 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
}
}

View 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';
}

View 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
}
}

View 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';
}

View File

@ -0,0 +1,2 @@
value = {"array":["Snap","Crackle","Pop"]}
array = [1,2,3,4]

View 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';
}

View File

@ -0,0 +1,2 @@
j1 = {"e":2.71828182845905,"pi":3.14159265358979}
j2 = [1,2,3,4,5]

View File

@ -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 (:)

View File

@ -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 (:)

View File

@ -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}));
}
}
}