Skip to content

Commit

Permalink
Improve jsonpointer unflatten
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Apr 2, 2020
1 parent 564f9d5 commit cfad3e2
Show file tree
Hide file tree
Showing 19 changed files with 266 additions and 44 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ For the examples below you need to include some header files and initialize a st

```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <iostream>

using namespace jsoncons; // for convenience
Expand Down Expand Up @@ -430,7 +430,7 @@ For the examples below you need to include some header files and initialize a bu
#include <iostream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons; // for convenience

Expand Down
4 changes: 2 additions & 2 deletions doc/Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -2199,7 +2199,7 @@ double sale_price = j.get_value_or<double>("sale_price", 22.0); // returns 22.0
```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
int main()
{
Expand Down Expand Up @@ -2349,7 +2349,7 @@ You can use [json_replace](ref/jsonpath/json_replace.md) in the `jsonpath` exten

```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons;

Expand Down
2 changes: 1 addition & 1 deletion doc/Pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ Example JSON file (booklist.json):
```
JSONPath examples:
```c++
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using jsoncons::jsonpath::json_query;

Expand Down
2 changes: 1 addition & 1 deletion doc/Tutorials/Basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ The JSON output `booklist.json`
```c++
#include <fstream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

// For convenience
using jsoncons::json;
Expand Down
4 changes: 2 additions & 2 deletions doc/ref/cbor/cbor.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ For the examples below you need to include some header files and initialize a bu
#include <iostream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons; // for convenience

Expand Down Expand Up @@ -500,7 +500,7 @@ Marilyn C, 0.9
```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
Expand Down
4 changes: 2 additions & 2 deletions doc/ref/jsonpath/json_query.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ The examples below use the JSON text from [Stefan Goessner's JSONPath](http://go

```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <fstream>

using namespace jsoncons;
Expand Down Expand Up @@ -244,7 +244,7 @@ Output:

```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons;

Expand Down
2 changes: 1 addition & 1 deletion doc/ref/jsonpath/json_replace.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Input JSON file `booklist.json`:
```
```c++
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons;
using namespace jsoncons::jsonpath;
Expand Down
17 changes: 17 additions & 0 deletions doc/ref/jsonpointer/unflatten_method.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### jsoncons::jsonpointer::unflatten_method

```c++
#include <jsoncons/jsonpointer/jsonpointer.hpp>

enum class unflatten_method{object=1,safe};
```
`unflatten_method` is used to specify how to unflatten a single depth
object of JSON Pointer-value pairs. There is no unique solution.
An integer appearing in a path could be an index or it could be an object key.
Value |Definition
-----------|-----------
unflatten_method()|If there is a zero in a path, it will start a new array.
object|Arrays will not be created when calling unflatten, rather, an integer appearing in a path is assumed to be an object key
safe|
2 changes: 1 addition & 1 deletion doc/ref/ubjson/ubjson.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ For the examples below you need to include some header files and initialize a bu
#include <iostream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/ubjson/ubjson.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons; // for convenience

Expand Down
2 changes: 1 addition & 1 deletion examples/src/basics_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <fstream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons;
using namespace jsoncons::jsonpath;
Expand Down
2 changes: 1 addition & 1 deletion examples/src/basics_wexamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <fstream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons;

Expand Down
2 changes: 1 addition & 1 deletion examples/src/cbor_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include "sample_types.hpp"
#include <string>
#include <iomanip>
Expand Down
2 changes: 1 addition & 1 deletion examples/src/cbor_typed_array_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include "sample_types.hpp"
#include <string>
#include <iomanip>
Expand Down
2 changes: 1 addition & 1 deletion examples/src/examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <map>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <fstream>

using namespace jsoncons;
Expand Down
2 changes: 1 addition & 1 deletion examples/src/json_constructor_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <map>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <fstream>

using namespace jsoncons;
Expand Down
2 changes: 1 addition & 1 deletion examples/src/readme_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <jsoncons_ext/csv/csv.hpp>
#include <string>
#include <vector>
Expand Down
2 changes: 1 addition & 1 deletion examples/src/ubjson_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <jsoncons/json.hpp>
#include <jsoncons_ext/ubjson/ubjson.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/jsonpath/json_query.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <string>
#include <iomanip>
#include <cassert>
Expand Down
120 changes: 118 additions & 2 deletions include/jsoncons_ext/jsonpointer/jsonpointer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,10 +984,120 @@ enum class pointer_state
return result;
}


// unflatten

enum class unflatten_method {object=1,safe};

template<class Json>
Json unflatten_to_safe_array (Json& value)
{
if (!value.is_object())
{
return value;
}
bool safe = true;
std::size_t index = 0;
for (const auto& item : value.object_range())
{
auto r = jsoncons::detail::to_integer<std::size_t>(item.key().data(),item.key().size());
if (!r || (index++ != r.value()))
{
safe = false;
break;
}
}

if (safe)
{
Json j(json_array_arg);
j.reserve(value.size());
for (auto& item : value.object_range())
{
j.emplace_back(std::move(item.value()));
}
Json a(json_array_arg);
for (auto& item : j.array_range())
{
a.emplace_back(unflatten_to_safe_array (item));
}
return a;
}
else
{
Json o(json_object_arg);
for (auto& item : value.object_range())
{
o.try_emplace(item.key(), unflatten_to_safe_array (item.value()));
}
return o;
}
}

template<class Json>
Json unflatten(const Json& value)
Json unflatten_to_default(const Json& value)
{
using char_type = typename Json::char_type;

if (JSONCONS_UNLIKELY(!value.is_object()))
{
JSONCONS_THROW(jsonpointer_error(jsonpointer_errc::argument_to_unflatten_invalid));
}
Json result;

for (const auto& item: value.object_range())
{
Json* part = &result;
basic_json_ptr<char_type> ptr(item.key());
for (auto it = ptr.begin(); it != ptr.end(); )
{
auto s = *it;
auto r = jsoncons::detail::to_integer<size_t>(s.data(), s.size());
if (r && (part->is_array() || r.value() == 0))
{
if (!part->is_array())
{
*part = Json(json_array_arg);
}
if (++it != ptr.end())
{
if (r.value()+1 > part->size())
{
Json& ref = part->emplace_back();
part = std::addressof(ref);
}
else
{
part = &part->at(r.value());
}
}
else
{
Json& ref = part->emplace_back(item.value());
part = std::addressof(ref);
}
}
else
{
if (++it != ptr.end())
{
auto res = part->try_emplace(s,Json());
part = &(res.first->value());
}
else
{
auto res = part->try_emplace(s, item.value());
part = &(res.first->value());
}
}
}
}

return result;
}

template<class Json>
Json unflatten_to_object(const Json& value, unflatten_method method = unflatten_method::safe)
{
using char_type = typename Json::char_type;

Expand Down Expand Up @@ -1017,7 +1127,13 @@ enum class pointer_state
}
}

return result;
return method == unflatten_method::safe ? unflatten_to_safe_array (result) : result;
}

template<class Json>
Json unflatten(const Json& value, unflatten_method method = unflatten_method())
{
return method == unflatten_method() ? unflatten_to_default(value) : unflatten_to_object(value,method);
}

} // namespace jsonpointer
Expand Down
Loading

0 comments on commit cfad3e2

Please sign in to comment.