Skip to content

Commit 7cff109

Browse files
committed
Add type & value fields to primitive json types
This aligns with how custom types are represented by the JsonExporter. * Update both toJson & fromJson functions in the JsonExporter * Add & update tests
1 parent 48f6c5b commit 7cff109

File tree

2 files changed

+70
-31
lines changed

2 files changed

+70
-31
lines changed

src/json_export.cpp

+44-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "behaviortree_cpp/json_export.h"
22

3+
namespace
4+
{
5+
constexpr std::string_view kTypeField = "__type";
6+
constexpr std::string_view kValueField = "value";
7+
} // namespace
8+
39
namespace BT
410
{
511

@@ -16,19 +22,23 @@ bool JsonExporter::toJson(const Any& any, nlohmann::json& dst) const
1622

1723
if(any.isString())
1824
{
19-
dst = any.cast<std::string>();
25+
dst[kTypeField] = "string";
26+
dst[kValueField] = any.cast<std::string>();
2027
}
2128
else if(type == typeid(int64_t))
2229
{
23-
dst = any.cast<int64_t>();
30+
dst[kTypeField] = "int64_t";
31+
dst[kValueField] = any.cast<int64_t>();
2432
}
2533
else if(type == typeid(uint64_t))
2634
{
27-
dst = any.cast<uint64_t>();
35+
dst[kTypeField] = "uint64_t";
36+
dst[kValueField] = any.cast<uint64_t>();
2837
}
2938
else if(type == typeid(double))
3039
{
31-
dst = any.cast<double>();
40+
dst[kTypeField] = "double";
41+
dst[kValueField] = any.cast<double>();
3242
}
3343
else
3444
{
@@ -51,33 +61,41 @@ JsonExporter::ExpectedEntry JsonExporter::fromJson(const nlohmann::json& source)
5161
{
5262
return nonstd::make_unexpected("json object is null");
5363
}
54-
if(source.is_string())
55-
{
56-
return Entry{ BT::Any(source.get<std::string>()),
57-
BT::TypeInfo::Create<std::string>() };
58-
}
59-
if(source.is_number_unsigned())
60-
{
61-
return Entry{ BT::Any(source.get<uint64_t>()), BT::TypeInfo::Create<uint64_t>() };
62-
}
63-
if(source.is_number_integer())
64-
{
65-
return Entry{ BT::Any(source.get<int64_t>()), BT::TypeInfo::Create<int64_t>() };
66-
}
67-
if(source.is_number_float())
68-
{
69-
return Entry{ BT::Any(source.get<double>()), BT::TypeInfo::Create<double>() };
70-
}
71-
if(source.is_boolean())
64+
if(!source.contains("__type"))
7265
{
73-
return Entry{ BT::Any(source.get<bool>()), BT::TypeInfo::Create<bool>() };
66+
return nonstd::make_unexpected("Missing field '__type'");
7467
}
7568

76-
if(!source.contains("__type"))
69+
if(source.contains("value"))
7770
{
78-
return nonstd::make_unexpected("Missing field '__type'");
71+
if(source[kValueField].is_string())
72+
{
73+
return Entry{ BT::Any(source[kValueField].get<std::string>()),
74+
BT::TypeInfo::Create<std::string>() };
75+
}
76+
if(source[kValueField].is_number_unsigned())
77+
{
78+
return Entry{ BT::Any(source[kValueField].get<uint64_t>()),
79+
BT::TypeInfo::Create<uint64_t>() };
80+
}
81+
if(source[kValueField].is_number_integer())
82+
{
83+
return Entry{ BT::Any(source[kValueField].get<int64_t>()),
84+
BT::TypeInfo::Create<int64_t>() };
85+
}
86+
if(source[kValueField].is_number_float())
87+
{
88+
return Entry{ BT::Any(source[kValueField].get<double>()),
89+
BT::TypeInfo::Create<double>() };
90+
}
91+
if(source[kValueField].is_boolean())
92+
{
93+
return Entry{ BT::Any(source[kValueField].get<bool>()),
94+
BT::TypeInfo::Create<bool>() };
95+
}
7996
}
80-
auto type_it = type_names_.find(source["__type"]);
97+
98+
auto type_it = type_names_.find(source[kTypeField]);
8199
if(type_it == type_names_.end())
82100
{
83101
return nonstd::make_unexpected("Type not found in registered list");

tests/gtest_json.cpp

+26-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#include "behaviortree_cpp/json_export.h"
44
#include "behaviortree_cpp/basic_types.h"
55

6+
namespace
7+
{
8+
constexpr std::string_view kTypeField = "__type";
9+
constexpr std::string_view kValueField = "value";
10+
} // namespace
11+
612
//----------- Custom types ----------
713

814
namespace TestTypes
@@ -95,16 +101,27 @@ TEST_F(JsonTest, TwoWaysConversion)
95101
TestTypes::Pose3D pose = { { 1, 2, 3 }, { 4, 5, 6, 7 } };
96102

97103
nlohmann::json json;
104+
exporter.toJson(BT::Any("string_val"), json["string"]);
98105
exporter.toJson(BT::Any(69), json["int"]);
106+
exporter.toJson(BT::Any(static_cast<uint64_t>(96)), json["uint"]);
99107
exporter.toJson(BT::Any(3.14), json["real"]);
100108
exporter.toJson(BT::Any(pose), json["pose"]);
101109

102110
std::cout << json.dump(2) << std::endl;
103111

104-
ASSERT_EQ(json["int"], 69);
105-
ASSERT_EQ(json["real"], 3.14);
112+
ASSERT_EQ(json["string"][kTypeField], "string");
113+
ASSERT_EQ(json["string"][kValueField], "string_val");
114+
115+
ASSERT_EQ(json["int"][kTypeField], "int64_t");
116+
ASSERT_EQ(json["int"][kValueField], 69);
117+
118+
ASSERT_EQ(json["uint"][kTypeField], "uint64_t");
119+
ASSERT_EQ(json["uint"][kValueField], 96);
120+
121+
ASSERT_EQ(json["real"][kTypeField], "double");
122+
ASSERT_EQ(json["real"][kValueField], 3.14);
106123

107-
ASSERT_EQ(json["pose"]["__type"], "Pose3D");
124+
ASSERT_EQ(json["pose"][kTypeField], "Pose3D");
108125
ASSERT_EQ(json["pose"]["pos"]["x"], 1);
109126
ASSERT_EQ(json["pose"]["pos"]["y"], 2);
110127
ASSERT_EQ(json["pose"]["pos"]["z"], 3);
@@ -126,8 +143,12 @@ TEST_F(JsonTest, TwoWaysConversion)
126143
ASSERT_EQ(pose.rot.y, pose2.rot.y);
127144
ASSERT_EQ(pose.rot.z, pose2.rot.z);
128145

129-
auto num = exporter.fromJson(json["int"])->first.cast<int>();
130-
ASSERT_EQ(num, 69);
146+
auto string_val = exporter.fromJson(json["string"])->first.cast<std::string>();
147+
ASSERT_EQ(string_val, "string_val");
148+
auto int_val = exporter.fromJson(json["int"])->first.cast<int>();
149+
ASSERT_EQ(int_val, 69);
150+
auto uint_val = exporter.fromJson(json["uint"])->first.cast<uint>();
151+
ASSERT_EQ(uint_val, 96);
131152
auto real = exporter.fromJson(json["real"])->first.cast<double>();
132153
ASSERT_EQ(real, 3.14);
133154
}

0 commit comments

Comments
 (0)