Skip to content

Commit 9f2283c

Browse files
authored
Merge pull request #5 from cpp-pre/feature/property-name-mapping
Feature/property name mapping
2 parents 4a7334c + f824b47 commit 9f2283c

File tree

8 files changed

+176
-30
lines changed

8 files changed

+176
-30
lines changed

.github/workflows/ci.yml

+4-14
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,20 @@ jobs:
66
build-wasm:
77
name: build-wasm
88
runs-on: ubuntu-latest
9-
container: nxxm/nxxm-ubuntu-develop
9+
container: tipibuild/tipi-ubuntu
1010
steps:
1111
- name: checkout
1212
uses: actions/checkout@v2
1313
- name: nxxm builds project
1414
run: |
15-
nxxm . --dont-upgrade --verbose --test all
16-
build-gcc:
17-
name: build-gcc
18-
runs-on: ubuntu-latest
19-
container: nxxm/nxxm-ubuntu-develop
20-
steps:
21-
- name: checkout
22-
uses: actions/checkout@v2
23-
- name: nxxm builds project
24-
run: |
25-
nxxm . --dont-upgrade --verbose --test all -t gcc-7-cxx17
15+
tipi . --dont-upgrade --verbose --test all -t wasm-cxx17
2616
build-clang-linux:
2717
name: build-clang-linux
2818
runs-on: ubuntu-latest
29-
container: nxxm/nxxm-ubuntu-develop
19+
container: tipibuild/tipi-ubuntu
3020
steps:
3121
- name: checkout
3222
uses: actions/checkout@v2
3323
- name: nxxm builds project
3424
run: |
35-
nxxm . --dont-upgrade --verbose --test all -t linux
25+
tipi . --dont-upgrade --verbose --test all -t linux-cxx17

.nxxm/deps

-4
This file was deleted.

.tipi/deps

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"nlohmann/json" : { "@" : "v3.11.1", "x" : ["benchmarks"] }
3+
, "platform" : [ "Boost::+boost" ]
4+
}

examples/from_json.cpp

+51-5
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,72 @@
11
#include <iostream>
22
#include <pre/json/from_json.hpp>
3+
#include <pre/json/mapping.hpp>
4+
#include <nlohmann/json.hpp>
5+
36

47
struct customer {
58
std::string name;
69
size_t money_spent;
710
std::vector<std::string> interests;
11+
std::optional<bool> is_private; // this property shall be mapped to the "private" key in the json
12+
std::vector<int> numbers;
813
};
914

1015
BOOST_FUSION_ADAPT_STRUCT(customer,
1116
name,
1217
money_spent,
13-
interests)
18+
interests,
19+
is_private,
20+
numbers)
1421

1522
int main() {
1623

24+
1725
std::string string_to_deserialize =
18-
"{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\"}";
26+
"{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\", \"private\": true, \"numbers\": [1,2,3]}";
27+
28+
// classic deserialization
29+
{
30+
customer my_customer = pre::json::from_json<customer>(string_to_deserialize);
31+
32+
std::cout << "Customer " << my_customer.name << " spent " <<
33+
my_customer.money_spent << std::endl;
34+
}
35+
36+
// with mapping deserialization
37+
{
38+
customer my_customer = pre::json::from_json<customer>(string_to_deserialize, [](nlohmann::json& jdoc) {
39+
jdoc["is_private"] = jdoc["private"];
40+
jdoc.erase("private");
41+
});
42+
43+
std::cout << "Customer " << my_customer.name << " spent " <<
44+
my_customer.money_spent << " is private:" << std::to_string(my_customer.is_private.value()) << std::endl;
45+
}
46+
47+
// with mapping helpers
48+
{
49+
customer my_customer = pre::json::from_json<customer>(string_to_deserialize, [](nlohmann::json& jdoc) {
50+
pre::json::remap_property(jdoc, "private", "is_private");
51+
});
52+
53+
std::cout << "Customer " << my_customer.name << " spent " <<
54+
my_customer.money_spent << " is private:" << std::to_string(my_customer.is_private.value()) << std::endl;
55+
}
1956

20-
customer my_customer = pre::json::from_json<customer>(string_to_deserialize);
57+
// with mapping and json_pointer helpers
58+
{
59+
std::string string_to_deserialize =
60+
"{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\", \"private\": true, \"numbers\": [1,2,3]}";
2161

22-
std::cout << "Customer " << my_customer.name << " spent " <<
23-
my_customer.money_spent << std::endl;
62+
customer my_customer = pre::json::from_json<customer>(string_to_deserialize, [](nlohmann::json& jdoc) {
63+
pre::json::remap_property(jdoc, "/private"_json_pointer, "/is_private"_json_pointer);
64+
pre::json::remap_property(jdoc, "/numbers/0"_json_pointer, "/numbersNew/2"_json_pointer);
65+
pre::json::remap_property(jdoc, "/money_spent"_json_pointer, "/numbers/0"_json_pointer);
66+
jdoc["money_spent"] = 0;
67+
std::cout << jdoc.dump(2) << std::endl;
68+
});
69+
}
2470

2571
return 0;
2672
}

examples/to_json.cpp

+24-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,43 @@
11
#include <iostream>
22
#include <pre/json/to_json.hpp>
3+
#include <pre/json/mapping.hpp>
34

45
struct customer {
56
std::string name;
67
size_t money_spent;
78
std::vector<std::string> interests;
9+
bool is_private;
810
};
911

1012
BOOST_FUSION_ADAPT_STRUCT(customer,
1113
name,
1214
money_spent,
13-
interests)
15+
interests,
16+
is_private)
1417

1518

1619
int main() {
1720

18-
customer my_customer{
19-
"Mr. Dupond",
20-
1000,
21-
{"sport articles", "food", "tools"}
22-
};
21+
{
22+
customer my_customer{
23+
"Mr. Dupond",
24+
1000,
25+
{"sport articles", "food", "tools"},
26+
true
27+
};
28+
29+
std::cout << pre::json::to_json(my_customer) << std::endl;
30+
31+
// with remapping
32+
std::cout << "With property 'is_private' mapped to 'private':\n"
33+
<< pre::json::to_json(
34+
my_customer,
35+
[](auto &jdoc) {
36+
pre::json::remap_property(jdoc, "/is_private"_json_pointer, "/private"_json_pointer);
37+
})
38+
<< std::endl;
39+
}
40+
2341

24-
std::cout << pre::json::to_json(my_customer) << std::endl;
2542
return 0;
2643
}

pre/json/from_json.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ namespace pre { namespace json {
7373
return object;
7474
}
7575

76+
/**
77+
* \brief Same as pre::json::from_json(const std::string&) but with an added mapper function
78+
*/
79+
template<class T>
80+
T from_json(const std::string& serialized_json, std::function<void(nlohmann::json&)> mapper) {
81+
nlohmann::json json_object = nlohmann::json::parse(serialized_json);
82+
mapper(json_object); // does whatever mapping is required
83+
T object;
84+
detail::dejsonizer dejsonizer(json_object);
85+
dejsonizer(object);
86+
return object;
87+
}
88+
7689
/**
7790
* \brief Same as pre::json::from_json(const std::string&) but directly with a JSON.
7891
*/

pre/json/mapping.hpp

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef PRE_JSON_MAPPING_HPP
2+
#define PRE_JSON_MAPPING_HPP
3+
4+
#include <nlohmann/json.hpp>
5+
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
6+
7+
namespace pre {
8+
namespace json {
9+
10+
11+
/**
12+
* @brief "Rername" a json key in the JSON object
13+
*
14+
* @param jdoc
15+
* @param psource source key name
16+
* @param pdest destination key name
17+
*/
18+
inline void remap_property(nlohmann::json& jdoc, std::string psource, std::string pdest) {
19+
jdoc[pdest] = jdoc[psource];
20+
jdoc.erase(psource);
21+
}
22+
23+
inline void remap_property(nlohmann::json& jdoc,
24+
nlohmann::json::json_pointer psource,
25+
nlohmann::json::json_pointer pdest
26+
) {
27+
// get reference to parent of JSON pointer ptr
28+
const auto original_psource = psource;
29+
const auto last_path = psource.back();
30+
psource.pop_back();
31+
auto& parent = jdoc.at(psource);
32+
33+
// remove child
34+
if (parent.is_object())
35+
{
36+
auto it = parent.find(last_path);
37+
if (it != parent.end())
38+
{
39+
jdoc[pdest] = jdoc[original_psource];
40+
parent.erase(it);
41+
}
42+
else
43+
{
44+
throw std::runtime_error("Could not find json key at: " + original_psource.to_string());
45+
}
46+
}
47+
else if (parent.is_array())
48+
{
49+
auto ix_deletion = std::stoi(last_path);
50+
auto value = jdoc[original_psource]; // copy source before deleting it
51+
52+
if(ix_deletion >= parent.size()) {
53+
throw std::runtime_error("Index out of range when accessing array at: " + original_psource.to_string());
54+
}
55+
56+
parent.erase(ix_deletion); // no need to range check manually, erase() does it already
57+
jdoc[pdest] = value;
58+
59+
}
60+
}
61+
}
62+
}
63+
64+
#endif

pre/json/to_json.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ namespace pre { namespace json {
6868
return json_object;
6969
}
7070

71+
/**
72+
* \brief Same as pre::json::to_json<T>(const T&) but with a post serialization mapper function
73+
*
74+
* \tparam T
75+
* \param value
76+
* \param mapper
77+
* \return An [nlohmann::json](https://github.com/nlohmann/json/) object directly streamable to std::cout or convertible to string.
78+
*/
79+
template<class T>
80+
nlohmann::json to_json(const T& value, std::function<void(nlohmann::json&)> mapper) {
81+
nlohmann::json json_object;
82+
detail::jsonizer jsonizer(json_object);
83+
jsonizer(value);
84+
mapper(json_object);
85+
return json_object;
86+
}
7187
}}
7288

7389
#endif

0 commit comments

Comments
 (0)