TEC
A lightweight C++ library enabling safe, efficient execution in multithreaded and concurrent systems.
Loading...
Searching...
No Matches
tec_json.hpp
Go to the documentation of this file.
1// Time-stamp: <Last changed 2026-02-20 15:58:13 by magnolia>
2/*----------------------------------------------------------------------
3------------------------------------------------------------------------
4Copyright (c) 2020-2026 The Emacs Cat (https://github.com/olddeuteronomy/tec).
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17------------------------------------------------------------------------
18----------------------------------------------------------------------*/
26#pragma once
27
28#include <string>
29#include <sstream>
30
31#include "tec/tec_def.hpp" // IWYU pragma: keep
32#include "tec/tec_memfile.hpp"
33#include "tec/tec_container.hpp"
34#include "tec/tec_serialize.hpp"
35#include "tec/tec_base64.hpp"
36
37
38namespace tec {
39
62struct Json {
63
65 static constexpr char sep[]{", "};
66
68 static constexpr char infix[]{": "};
69
79 inline static void print_name(std::ostringstream& os, const char* name) {
80 if (name) {
81 os << "\"" << name << "\"" << infix;
82 }
83 }
84
92 static std::string json(const std::string& val, const char* name = nullptr) {
93 std::ostringstream os;
94 print_name(os, name);
95 os << "\"" << val << "\"";
96 return os.str();
97 }
98
106 static std::string json(const Blob& val, const char* name = nullptr) {
107 std::ostringstream os;
108 print_name(os, name);
109 os << "\"" << base64::encode(val.str()) << "\"";
110 return os.str();
111 }
112
120 static std::string json_bool(const bool& val, const char* name = nullptr) {
121 constexpr static char t[]{"true"};
122 constexpr static char f[]{"false"};
123 std::ostringstream os;
124 print_name(os, name);
125 os << (val ? t : f);
126 return os.str();
127 }
128
129 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130 *
131 * Containers
132 *
133 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
134
145 template <typename TContainer>
146 static std::string json_container(const TContainer& c, const char* name) {
147 std::ostringstream os;
148 print_name(os, name);
149 bool first{true};
150 os << "[";
151 for( const auto& e: c ) {
152 if(first) {
153 os << e;
154 first = false;
155 }
156 else {
157 os << sep << e;
158 }
159 }
160 os << "]";
161 return os.str();
162 }
163
174 template <typename TMap>
175 static std::string json_map(const TMap& m, const char* name) {
176 std::ostringstream os;
177 print_name(os, name);
178 bool first{true};
179 os << "{";
180 for (const auto& [k, v]: m) {
181 if(first) {
182 os << k << infix << v;
183 first = false;
184 }
185 else {
186 os << sep << k << infix << v;
187
188 }
189 }
190 os << "}";
191 return os.str();
192 }
193
194 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195 *
196 * Serializable object
197 *
198 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
199
210 template <typename TObject>
211 static std::string json_object(const TObject& obj, const char* name) {
212 std::ostringstream os;
213 print_name(os, name);
214 os << "{" << obj.to_json() << "}";
215 return os.str();
216 }
217
218 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219 *
220 * Generic fallback
221 *
222 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
223
238 template <typename T>
239 static std::string json(const T& val, const char* name) {
240 std::ostringstream os;
241 if constexpr (is_serializable_v<T>) {
242 return json_object(val, name);
243 }
244 else if constexpr (is_map_v<T>) {
245 return json_map(val, name);
246 }
247 else if constexpr (is_container_v<T>) {
248 return json_container(val, name);
249 }
250 else if constexpr (std::is_same_v<T, bool>) {
251 return json_bool(val, name);
252 }
253 else {
254 // Any scalar
255 print_name(os, name);
256 os << val;
257 }
258 return os.str();
259 }
260
261
272 template <typename T>
273 std::string operator()(const T& val, const char* name) {
274 return json(val, name);
275 }
276
286 template <typename T>
287 std::string operator()(const T& val) {
288 return json(val, nullptr);
289 }
290};
291
292} // namespace tec
293
294/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
295*
296* USAGE
297*
298
299struct Person: tec::Serializable {
300 using json = tec::Json;
301 static constexpr auto sep{tec::Json::sep};
302
303 short age;
304 std::string name;
305 std::string surname;
306
307 friend std::ostream& operator << (std::ostream& os, const Person& p) {
308 os << json{}(p);
309 return os;
310 }
311
312 std::string to_json() const override {
313 std::ostringstream os;
314 os
315 << json{}(age, "age") << sep
316 << json{}(name, "name") << sep
317 << json{}(surname, "surname")
318 ;
319 return os.str();
320 }
321};
322
323*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
A byte buffer class with stream-like read/write semantics.
Definition tec_memfile.hpp:50
const std::string & str() const noexcept
Returns a const reference to the internal string buffer.
Definition tec_memfile.hpp:235
Utility class for generating minimal, valid JSON strings at compile-time and runtime.
Definition tec_json.hpp:62
static std::string json_bool(const bool &val, const char *name=nullptr)
Serialize a boolean as JSON true or false.
Definition tec_json.hpp:120
static constexpr char infix[]
Separator used between object key and value.
Definition tec_json.hpp:68
static std::string json(const T &val, const char *name)
Generic JSON serializer with automatic type dispatching.
Definition tec_json.hpp:239
static std::string json(const std::string &val, const char *name=nullptr)
Serialize a std::string as a JSON string literal.
Definition tec_json.hpp:92
std::string operator()(const T &val)
Functor interface — serialize without name (root value).
Definition tec_json.hpp:287
std::string operator()(const T &val, const char *name)
Functor interface — serialize with explicit name.
Definition tec_json.hpp:273
static void print_name(std::ostringstream &os, const char *name)
Helper to optionally emit a JSON key name.
Definition tec_json.hpp:79
static std::string json_object(const TObject &obj, const char *name)
Serialize a tec::Serializable-derived object as a nested JSON object.
Definition tec_json.hpp:211
static constexpr char sep[]
Separator used between array/object elements.
Definition tec_json.hpp:65
static std::string json_map(const TMap &m, const char *name)
Serialize unordered map-like containers as JSON objects.
Definition tec_json.hpp:175
static std::string json_container(const TContainer &c, const char *name)
Serialize any container (with .begin()/.end()) as a JSON array.
Definition tec_json.hpp:146
static std::string json(const Blob &val, const char *name=nullptr)
Serialize a Blob object as a base64-encoded JSON string.
Definition tec_json.hpp:106
A header-only Base64 encoder/decoder.
Generic container and map traits.
Common definitions and utilities for the tec namespace.
A byte buffer class with stream-like read/write semantics.
auto name(const Message &msg) noexcept
Retrieves the type name of a message's content for registering the corresponding message handler.
Definition tec_message.hpp:84
The base interface for serializable objects.