Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
2fa8ea0f
Commit
2fa8ea0f
authored
Oct 08, 2016
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
started fixing #323
parent
a0ef5a19
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
101 additions
and
15 deletions
+101
-15
operatorjson_pointer.cpp
doc/examples/operatorjson_pointer.cpp
+1
-1
json.hpp
src/json.hpp
+43
-6
json.hpp.re2c
src/json.hpp.re2c
+43
-6
unit-json_pointer.cpp
test/src/unit-json_pointer.cpp
+7
-2
unit-regression.cpp
test/src/unit-regression.cpp
+7
-0
No files found.
doc/examples/operatorjson_pointer.cpp
View file @
2fa8ea0f
...
@@ -40,7 +40,7 @@ int main()
...
@@ -40,7 +40,7 @@ int main()
// output the changed array
// output the changed array
std
::
cout
<<
j
[
"array"
]
<<
'\n'
;
std
::
cout
<<
j
[
"array"
]
<<
'\n'
;
// "change" the arry element past the end
// "change" the arr
a
y element past the end
j
[
"/array/-"
_json_pointer
]
=
55
;
j
[
"/array/-"
_json_pointer
]
=
55
;
// output the changed array
// output the changed array
std
::
cout
<<
j
[
"array"
]
<<
'\n'
;
std
::
cout
<<
j
[
"array"
]
<<
'\n'
;
...
...
src/json.hpp
View file @
2fa8ea0f
...
@@ -9436,6 +9436,12 @@ basic_json_parser_63:
...
@@ -9436,6 +9436,12 @@ basic_json_parser_63:
/*!
/*!
@brief return a reference to the pointed to value
@brief return a reference to the pointed to value
@note This version does not throw if a value is not present, but tries
to create nested values instead. For instance, calling this function
with pointer `"/this/that"` on a null value is equivalent to calling
`operator[]("this").operator[]("that")` on that value, effectively
changing the null value to an object.
@param[in] ptr a JSON value
@param[in] ptr a JSON value
@return reference to the JSON value pointed to by the JSON pointer
@return reference to the JSON value pointed to by the JSON pointer
...
@@ -9450,6 +9456,12 @@ basic_json_parser_63:
...
@@ -9450,6 +9456,12 @@ basic_json_parser_63:
{
{
for
(
const
auto
&
reference_token
:
reference_tokens
)
for
(
const
auto
&
reference_token
:
reference_tokens
)
{
{
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
switch
(
ptr
->
m_type
)
switch
(
ptr
->
m_type
)
{
{
case
value_t
:
:
object
:
case
value_t
:
:
object
:
...
@@ -9461,12 +9473,6 @@ basic_json_parser_63:
...
@@ -9461,12 +9473,6 @@ basic_json_parser_63:
case
value_t
:
:
array
:
case
value_t
:
:
array
:
{
{
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
if
(
reference_token
==
"-"
)
if
(
reference_token
==
"-"
)
{
{
// explicityly treat "-" as index beyond the end
// explicityly treat "-" as index beyond the end
...
@@ -9480,6 +9486,37 @@ basic_json_parser_63:
...
@@ -9480,6 +9486,37 @@ basic_json_parser_63:
break
;
break
;
}
}
// null values are converted to arrays or objects
case
value_t
:
:
null
:
{
// check if reference token is a number
const
bool
nums
=
std
::
all_of
(
reference_token
.
begin
(),
reference_token
.
end
(),
[](
const
char
x
)
{
return
std
::
isdigit
(
x
);
});
if
(
nums
)
{
// if reference token consists solely of numbers
// use it as array index -> create array
ptr
=
&
ptr
->
operator
[](
static_cast
<
size_type
>
(
std
::
stoi
(
reference_token
)));
}
else
if
(
reference_token
==
"-"
)
{
// explicityly treat "-" as index beyond the end
// which is 0 for an empty array -> create array
ptr
=
&
ptr
->
operator
[](
0
);
}
else
{
// treat reference token as key -> create object
ptr
=
&
ptr
->
operator
[](
reference_token
);
}
break
;
}
default
:
default
:
{
{
throw
std
::
out_of_range
(
"unresolved reference token '"
+
reference_token
+
"'"
);
throw
std
::
out_of_range
(
"unresolved reference token '"
+
reference_token
+
"'"
);
...
...
src/json.hpp.re2c
View file @
2fa8ea0f
...
@@ -8733,6 +8733,12 @@ class basic_json
...
@@ -8733,6 +8733,12 @@ class basic_json
/*!
/*!
@brief return a reference to the pointed to value
@brief return a reference to the pointed to value
@note This version does not throw if a value is not present, but tries
to create nested values instead. For instance, calling this function
with pointer `"/this/that"` on a null value is equivalent to calling
`operator[]("this").operator[]("that")` on that value, effectively
changing the null value to an object.
@param[in] ptr a JSON value
@param[in] ptr a JSON value
@return reference to the JSON value pointed to by the JSON pointer
@return reference to the JSON value pointed to by the JSON pointer
...
@@ -8747,6 +8753,12 @@ class basic_json
...
@@ -8747,6 +8753,12 @@ class basic_json
{
{
for (const auto& reference_token : reference_tokens)
for (const auto& reference_token : reference_tokens)
{
{
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
throw std::domain_error("array index must not begin with '0'");
}
switch (ptr->m_type)
switch (ptr->m_type)
{
{
case value_t::object:
case value_t::object:
...
@@ -8758,12 +8770,6 @@ class basic_json
...
@@ -8758,12 +8770,6 @@ class basic_json
case value_t::array:
case value_t::array:
{
{
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
throw std::domain_error("array index must not begin with '0'");
}
if (reference_token == "-")
if (reference_token == "-")
{
{
// explicityly treat "-" as index beyond the end
// explicityly treat "-" as index beyond the end
...
@@ -8777,6 +8783,37 @@ class basic_json
...
@@ -8777,6 +8783,37 @@ class basic_json
break;
break;
}
}
// null values are converted to arrays or objects
case value_t::null:
{
// check if reference token is a number
const bool nums = std::all_of(reference_token.begin(),
reference_token.end(),
[](const char x)
{
return std::isdigit(x);
});
if (nums)
{
// if reference token consists solely of numbers
// use it as array index -> create array
ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
}
else if (reference_token == "-")
{
// explicityly treat "-" as index beyond the end
// which is 0 for an empty array -> create array
ptr = &ptr->operator[](0);
}
else
{
// treat reference token as key -> create object
ptr = &ptr->operator[](reference_token);
}
break;
}
default:
default:
{
{
throw std::out_of_range("unresolved reference token '" + reference_token + "'");
throw std::out_of_range("unresolved reference token '" + reference_token + "'");
...
...
test/src/unit-json_pointer.cpp
View file @
2fa8ea0f
...
@@ -109,8 +109,13 @@ TEST_CASE("JSON pointers")
...
@@ -109,8 +109,13 @@ TEST_CASE("JSON pointers")
CHECK
(
j
[
json
::
json_pointer
(
"/m~0n"
)]
==
j
[
"m~n"
]);
CHECK
(
j
[
json
::
json_pointer
(
"/m~0n"
)]
==
j
[
"m~n"
]);
// unescaped access
// unescaped access
CHECK_THROWS_AS
(
j
[
json
::
json_pointer
(
"/a/b"
)],
std
::
out_of_range
);
// access to nonexisting values yield object creation
CHECK_THROWS_WITH
(
j
[
json
::
json_pointer
(
"/a/b"
)],
"unresolved reference token 'b'"
);
CHECK_NOTHROW
(
j
[
json
::
json_pointer
(
"/a/b"
)]
=
42
);
CHECK
(
j
[
"a"
][
"b"
]
==
json
(
42
));
CHECK_NOTHROW
(
j
[
json
::
json_pointer
(
"/a/c/1"
)]
=
42
);
CHECK
(
j
[
"a"
][
"c"
]
==
json
({
nullptr
,
42
}));
CHECK_NOTHROW
(
j
[
json
::
json_pointer
(
"/a/d/-"
)]
=
42
);
CHECK
(
j
[
"a"
][
"d"
]
==
json
::
array
({
42
}));
// "/a/b" works for JSON {"a": {"b": 42}}
// "/a/b" works for JSON {"a": {"b": 42}}
CHECK
(
json
({{
"a"
,
{{
"b"
,
42
}}}})[
json
::
json_pointer
(
"/a/b"
)]
==
json
(
42
));
CHECK
(
json
({{
"a"
,
{{
"b"
,
42
}}}})[
json
::
json_pointer
(
"/a/b"
)]
==
json
(
42
));
...
...
test/src/unit-regression.cpp
View file @
2fa8ea0f
...
@@ -482,4 +482,11 @@ TEST_CASE("regression tests")
...
@@ -482,4 +482,11 @@ TEST_CASE("regression tests")
CHECK_NOTHROW
(
j
<<
f
);
CHECK_NOTHROW
(
j
<<
f
);
}
}
}
}
SECTION
(
"issue #323 - add nested object capabilities to pointers"
)
{
json
j
;
j
[
"/this/that"
_json_pointer
]
=
27
;
CHECK
(
j
==
json
({{
"this"
,
{{
"that"
,
27
}}}}));
}
}
}
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