@@ -92,32 +92,9 @@ struct JSON
9292 }
9393 }
9494
95- template <class T > inline void array (const T &val) const
96- {
97- json += ' [' ;
98- bool not_first = false ;
99- for (const auto &e : val) {
100- if (not_first)
101- json += ' ,' ;
102- else
103- not_first = true ;
104- any (e);
105- }
106- json += ' ]' ;
107- }
95+ template <class T > inline void array (const T &val) const ;
10896
109- template <class T > inline void tupleObj (const T &val) const
110- {
111- std::apply (
112- [this ](const auto &arg, const auto &...args )
113- {
114- json += ' [' ;
115- any (arg);
116- ((json += ' ,' , any (args)), ...);
117- json += ' ]' ;
118- },
119- val);
120- }
97+ template <class T > inline void tupleObj (const T &val) const ;
12198
12299 template <class T > void dynamicObj (const T &val) const ;
123100
@@ -267,26 +244,36 @@ template <class J> struct JSONNoBaseAutoObj : JSONAutoObj
267244 }
268245};
269246
270- struct JSONObj : JSON
247+ template < char open, char close> struct JSONRepeat : JSON
271248{
272249 using JSON::JSON;
273250
274- inline ~JSONObj ()
251+ JSONRepeat (JSONRepeat &&) = delete ;
252+ JSONRepeat (const JSONRepeat &) = delete ;
253+ JSONRepeat &operator =(const JSONRepeat &) = delete ;
254+ JSONRepeat &operator =(JSONRepeat &&) = delete ;
255+
256+ inline ~JSONRepeat ()
275257 {
276- if (!was) json += ' { ' ;
277- json += ' } ' ;
258+ if (!was) json += open ;
259+ json += close ;
278260 }
279261
280- JSONObj (JSONObj &&) = delete ;
281- JSONObj (const JSONObj &) = delete ;
282- JSONObj &operator =(const JSONObj &) = delete ;
283- JSONObj &operator =(JSONObj &&) = delete ;
262+ void sep () { json += std::exchange (was, true ) ? ' ,' : open; }
263+
264+ bool was{};
265+ };
266+
267+ struct JSONArr ;
268+
269+ struct JSONObj : protected JSONRepeat <' {' , ' }' >
270+ {
271+ using JSONRepeat::JSONRepeat;
284272
285273 template <bool KeyNoEscape = true >
286274 inline JSON &key (std::string_view key)
287275 {
288- json += std::exchange (was, true ) ? ' ,' : ' {' ;
289-
276+ sep ();
290277 json += ' \" ' ;
291278 if constexpr (KeyNoEscape)
292279 json.append (key);
@@ -304,6 +291,9 @@ struct JSONObj : JSON
304291 return JSONObj{json};
305292 }
306293
294+ template <bool KeyNoEscape = true >
295+ inline JSONArr nestedArr (std::string_view key);
296+
307297 template <bool KeyNoEscape = true >
308298 inline JSONObj &raw (std::string_view key, const std::string &str)
309299 {
@@ -327,10 +317,48 @@ struct JSONObj : JSON
327317 any (val);
328318 return std::move (*this );
329319 }
320+ };
330321
331- bool was{};
322+ struct JSONArr : protected JSONRepeat <' [' , ' ]' >
323+ {
324+ using JSONRepeat::JSONRepeat;
325+
326+ template <class T > inline JSONArr &operator <<(const T &obj)
327+ {
328+ sep ();
329+ any (obj);
330+ return *this ;
331+ }
332+
333+ inline JSONArr nested ()
334+ {
335+ sep ();
336+ return JSONArr{json};
337+ }
338+
339+ inline JSONObj nestedObj ()
340+ {
341+ sep ();
342+ return JSONObj{json};
343+ }
332344};
333345
346+ template <class T > inline void JSON::array (const T &val) const
347+ {
348+ auto arr = JSONArr{json};
349+ for (const auto &e : val) arr << e;
350+ }
351+
352+ template <class T > inline void JSON::tupleObj (const T &val) const
353+ {
354+ std::apply (
355+ [this ](const auto &...args )
356+ {
357+ (JSONArr{json} << ... << args);
358+ },
359+ val);
360+ }
361+
334362template <class T > inline void JSON::dynamicObj (const T &val) const
335363{
336364 auto j = JSONObj{json};
@@ -344,6 +372,13 @@ template <class T> inline void JSON::staticObj(const T &val) const
344372 Refl::visit (JSONNoBaseAutoObj<T>{json}, val);
345373}
346374
375+ template <bool KeyNoEscape>
376+ inline JSONArr JSONObj::nestedArr (std::string_view key)
377+ {
378+ this ->key <KeyNoEscape>(key);
379+ return JSONArr{json};
380+ }
381+
347382template <class T > inline std::string toJSON (const T &v)
348383{
349384 std::string res;
0 commit comments