Skip to content

Commit 38b32ab

Browse files
committed
Sub objects
Signed-off-by: TymianekPL <[email protected]>
1 parent 1e4d45c commit 38b32ab

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

Test/Test.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ int main()
77
std::println("{}", object);
88
object["test1"] = "Hello World";
99
object["test2"] = 123.0;
10+
object["sub"]["veryNested"] = 6.0;
11+
1012
std::println("{}", object);
1113
std::println("object[\"test1\"] = {}", object["test1"]);
14+
const std::string test = object["test1"];
15+
std::println("test = {}", test);
1216
}

cppjson/include/cppjson/object.hpp

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ namespace cppjson
6868
explicit ObjectProxy(JsonObject& object) : _object(std::ref(object)) {}
6969

7070
template <typename T>
71+
requires (!std::same_as<std::remove_cvref_t<T>, JsonObject>)
7172
explicit(false) operator T&()
7273
{
7374
return this->_object.get().As<T>();
7475
}
7576

7677
template <typename T>
78+
requires (!std::same_as<std::remove_cvref_t<T>, JsonObject>)
7779
explicit(false) operator const T&() const
7880
{
7981
return this->_object.get().As<T>();
@@ -90,6 +92,8 @@ namespace cppjson
9092
{
9193
return static_cast<std::string&>(*this) = std::string{ str };
9294
}
95+
96+
ObjectProxy operator[](const std::string& key);
9397
private:
9498
std::reference_wrapper<JsonObject> _object;
9599

@@ -106,6 +110,8 @@ namespace cppjson
106110
{
107111
return this->_object.get().As<T>();
108112
}
113+
114+
ConstObjectProxy operator[](const std::string& key) const;
109115
private:
110116
std::reference_wrapper<const JsonObject> _object;
111117

@@ -127,10 +133,12 @@ namespace cppjson
127133
private:
128134
std::unordered_map<std::string, JsonObject> _nodes{};
129135

136+
friend struct std::formatter<cppjson::JsonObject>;
130137
friend struct std::formatter<cppjson::Object>;
131138
};
132139
} // namespace cppjson
133140

141+
134142
template <>
135143
struct std::formatter<cppjson::JsonObject>
136144
{
@@ -144,54 +152,73 @@ struct std::formatter<cppjson::JsonObject>
144152
case cppjson::JsonType::Bool: return std::format_to(context.out(), "{}", object.DangerousAs<bool>());
145153
case cppjson::JsonType::Number: return std::format_to(context.out(), "{}", object.DangerousAs<double>());
146154
case cppjson::JsonType::String: return std::format_to(context.out(), "\"{}\"", object.DangerousAs<std::string>());
155+
case cppjson::JsonType::Object:
156+
{
157+
const auto& node = object.DangerousAs<cppjson::Object>();
158+
159+
std::string built = "{ ";
160+
for (const auto& [key, value] : node._nodes)
161+
built += std::format("\"{}\": {}, ", key, value);
162+
163+
if (!node._nodes.empty()) // remove trailing commas
164+
{
165+
built.pop_back();
166+
built.pop_back();
167+
built += " }";
168+
}
169+
else built += "}";
170+
171+
return std::format_to(context.out(), "{}", built);
172+
}
147173
}
148174

149175
throw std::logic_error("Unknown type");
150176
}
151177
};
152178

153179
template <>
154-
struct std::formatter<cppjson::Object::ObjectProxy>
180+
struct std::formatter<cppjson::Object>
155181
{
156182
constexpr auto parse(std::format_parse_context& context) { return context.begin(); }
157183

158-
auto format(const cppjson::Object::ObjectProxy& object, std::format_context& context) const
184+
auto format(const cppjson::Object& object, std::format_context& context) const
159185
{
160-
return std::format_to(context.out(), "{}", object._object.get());
186+
std::string built = "{ ";
187+
for (const auto& [key, value] : object._nodes)
188+
built += std::format("\"{}\": {}, ", key, value);
189+
190+
if (!object._nodes.empty()) // remove trailing commas
191+
{
192+
built.pop_back();
193+
built.pop_back();
194+
built += " }";
195+
}
196+
else built += "}";
197+
198+
return std::format_to(context.out(), "{}", built);
161199
}
162200
};
163201

164202

165203
template <>
166-
struct std::formatter<cppjson::Object::ConstObjectProxy>
204+
struct std::formatter<cppjson::Object::ObjectProxy>
167205
{
168206
constexpr auto parse(std::format_parse_context& context) { return context.begin(); }
169207

170-
auto format(const cppjson::Object::ConstObjectProxy& object, std::format_context& context) const
208+
auto format(const cppjson::Object::ObjectProxy& object, std::format_context& context) const
171209
{
172210
return std::format_to(context.out(), "{}", object._object.get());
173211
}
174212
};
175213

214+
176215
template <>
177-
struct std::formatter<cppjson::Object>
216+
struct std::formatter<cppjson::Object::ConstObjectProxy>
178217
{
179218
constexpr auto parse(std::format_parse_context& context) { return context.begin(); }
180219

181-
auto format(const cppjson::Object& object, std::format_context& context) const
220+
auto format(const cppjson::Object::ConstObjectProxy& object, std::format_context& context) const
182221
{
183-
std::string built = "{ ";
184-
for (const auto& [key, value] : object._nodes)
185-
built += std::format("\"{}\": {}, ", key, value);
186-
187-
if (!object._nodes.empty()) // remove trailing commas
188-
{
189-
built.pop_back();
190-
built.pop_back();
191-
built += " }";
192-
}
193-
else built += "}";
194-
195-
return std::format_to(context.out(), "{}", built);
222+
return std::format_to(context.out(), "{}", object._object.get());
196223
}
197224
};

cppjson/src/object.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,14 @@ const std::nullptr_t& cppjson::JsonObject::As<std::nullptr_t>() const noexcept(f
119119
if (this->_dataType != JsonType::Null) throw std::logic_error("Cannot convert this object to a null");
120120
return DangerousAs<std::nullptr_t>();
121121
}
122+
123+
cppjson::Object::ObjectProxy cppjson::Object::ObjectProxy::operator[](const std::string& key)
124+
{
125+
return ObjectProxy{ this->_object.get().As<Object>()[key] };
126+
}
127+
128+
129+
cppjson::Object::ConstObjectProxy cppjson::Object::ConstObjectProxy::operator[](const std::string& key) const
130+
{
131+
return ConstObjectProxy{ this->_object.get().As<Object>()[key] };
132+
}

0 commit comments

Comments
 (0)