izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
izzi-json-basics.h
Go to the documentation of this file.
1// alpha60/izzi serialize/deserialize to/from JSON -*- mode: C++ -*-
2
3// Copyright (c) 2016-2025, Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the alpha60 library. This library is free
6// software; you can redistribute it and/or modify it under the terms
7// of the GNU General Public License as published by the Free Software
8// Foundation; either version 3, or (at your option) any later
9// version.
10
11// This library is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15
16#ifndef izzi_JSON_BASICS_H
17#define izzi_JSON_BASICS_H 1
18
19#include <iostream>
20#include <sstream>
21#include <fstream>
22
23#define RAPIDJSON_HAS_STDSTRING 1
24
25#ifdef __clang__
26#include "prettywriter.h"
27#include "pointer.h"
28#include "filereadstream.h"
29#include "reader.h"
30#include "document.h"
31#include "error/en.h"
32#else
33#include "rapidjson/prettywriter.h"
34#include "rapidjson/pointer.h"
35#include "rapidjson/filereadstream.h"
36#include "rapidjson/reader.h"
37#include "rapidjson/document.h"
38#include "rapidjson/error/en.h"
39#endif
40
41namespace svg {
42
43/// Aliases/using.
44namespace rj = rapidjson;
45using jsonstream = rj::PrettyWriter<rj::StringBuffer>;
46
47
48/// Serialize set of id_type
49void
50serialize_id_types_json(jsonstream& writer, const auto& ids, const string tag)
51{
52 writer.String(tag);
53 writer.StartArray();
54 uint countp(1);
55 for (const auto& id : ids)
56 {
57 auto [ count, name ] = id;
58
59 writer.StartObject();
60
61 writer.String("number");
62 writer.Int(countp++);
63
64 writer.String("id");
65 writer.String(name);
66
67 writer.String("count");
68 writer.Int(count);
69
70 writer.EndObject();
71 }
72 writer.EndArray();
73}
74
75
76/// Deserialize input string.
77rj::Document
79{
80 // DOM
81 rj::Document dom;
82 dom.Parse(json.c_str());
83 if (dom.HasParseError())
84 {
85 std::cerr << "error: cannot parse input string " << std::endl;
86 std::cerr << rj::GetParseError_En(dom.GetParseError()) << std::endl;
87 std::cerr << dom.GetErrorOffset() << std::endl;
88 }
89 return dom;
90}
91
92
93/// Deserialize input file.
94rj::Document
95deserialize_json_to_dom(const string input_file)
96{
97 // Deserialize input file.
98 std::ifstream ifs(input_file);
99 string json;
100 if (ifs.good())
101 {
102 std::ostringstream oss;
103 oss << ifs.rdbuf();
104 json = oss.str();
105 }
106 else
107 {
108 std::cerr << "error: cannot open input file " << input_file << std::endl;
109 }
110
112}
113
114
115/// Load JSON file to in-memory DOM.
116rj::Document
117deserialize_json_to_dom_object(const string input_file)
118{
119 rj::Document dom = deserialize_json_to_dom(input_file);
120
121 if (!dom.IsObject())
122 {
123 std::cerr << "error: expected document to be an object "
124 << "in file: "<< input_file << std::endl;
125 }
126
127 return dom;
128}
129
130
131/// Load JSON file to in-memory DOM array.
132rj::Document
133deserialize_json_to_dom_array(const string input_file)
134{
135 rj::Document dom = deserialize_json_to_dom(input_file);
136
137 if (!dom.IsArray())
138 {
139 std::cerr << "error: expected document to be an array "
140 << "in file: "<< input_file << std::endl;
141 }
142
143 return dom;
144}
145
146
147/// Search DOM for string literals.
148string
149search_dom_for_string_field(const rj::Document& dom, const string finds)
150{
151 string found;
152 if (!dom.HasParseError() && dom.HasMember(finds.c_str()))
153 {
154 const rj::Value& a = dom[finds.c_str()];
155 if (a.IsString())
156 found = a.GetString();
157 }
158 return found;
159}
160
161
162/// Search DOM for integer values.
163int
164search_dom_for_int_field(const rj::Document& dom, const string finds)
165{
166 int found(0);
167 if (!dom.HasParseError() && dom.HasMember(finds.c_str()))
168 {
169 const rj::Value& a = dom[finds.c_str()];
170 if (a.IsInt())
171 found = a.GetInt();
172 }
173 return found;
174}
175
176
177/// Extract from raw JSON value to double.
178double
180{
181 double ret(0.00123);
182 const bool stringp = v.IsString();
183 const bool numberp = v.IsNumber();
184 const bool boolp = v.IsBool();
185 if (numberp)
186 {
187 // https://miloyip.github.io/rapidjson/md_doc_tutorial.html#QueryNumber
188 ret = v.GetDouble();
189 }
190 if (stringp)
191 {
192 string s = v.GetString();
193 ret = std::stod(s);
194 }
195 if (boolp)
196 ret = static_cast<double>(v.GetBool());
197
198 return ret;
199}
200
201
202/// Deserialize json array,
203/// extract specific fields from array objects,
204/// return as vec of point_2t
205///
206/// jdata == input is path + filename of input JSON data file
207/// afield == pointer in json file dom to specific array's data
208/// field1 == x field to extract in array
209/// field2 == y field to extract in array
210vrange
211deserialize_json_array_object_field_n(const string jdata, const string afield,
212 const string field1, const string field2,
213 const bool verbosep = true)
214{
215 vrange ret;
216
217 // Load input JSON data file into DOM.
218 // Assuming 2025-era mozilla pageload json input styles, aka
219 // /home/bkoz/src/mozilla-a11y-data-visual-forms/data/2025-01-27-minimal.json
220 rj::Document dom(deserialize_json_to_dom(jdata));
221 rj::Value* ap = rj::Pointer(afield.c_str()).Get(dom);
222 if (ap)
223 {
224 const rj::Value& av = *ap;
225 if (av.IsArray())
226 {
227 for (uint j = 0; j < av.Size(); ++j)
228 {
229 double x(0);
230 double y(0);
231 const rj::Value& vssub = av[j];
232 const bool f1p = vssub.HasMember(field1.c_str());
233 const bool f2p = vssub.HasMember(field2.c_str());
234 if (f1p)
235 {
236 const rj::Value& vx = vssub[field1.c_str()];
238 }
239 if (f2p)
240 {
241 const rj::Value& vy = vssub[field2.c_str()];
243 }
244
245 if (f1p && f2p)
246 ret.push_back(std::make_tuple(x, y));
247 else
248 {
249 string m("deserialize_json_array_object_field_n:: error ");
250 m += k::tab;
251 m += "iteration " + std::to_string(j);
252 m += " not found";
253 m += k::newline;
254
255 if (verbosep)
256 throw std::runtime_error(m);
257 }
258 }
259 }
260 }
261
262 return ret;
263}
264
265} // namespace svg
266#endif
double extract_dom_value_to_double(const rj::Value &v)
Extract from raw JSON value to double.
int search_dom_for_int_field(const rj::Document &dom, const string finds)
Search DOM for integer values.
rj::PrettyWriter< rj::StringBuffer > jsonstream
Aliases/using.
rj::Document deserialize_json_to_dom(const string input_file)
Deserialize input file.
rj::Document deserialize_json_to_dom_array(const string input_file)
Load JSON file to in-memory DOM array.
std::vector< point_2t > vrange
Definition a60-svg.h:86
rj::Document deserialize_json_to_dom_object(const string input_file)
Load JSON file to in-memory DOM.
unsigned int uint
Definition a60-svg.h:57
void serialize_id_types_json(jsonstream &writer, const auto &ids, const string tag)
Serialize set of id_type.
string search_dom_for_string_field(const rj::Document &dom, const string finds)
Search DOM for string literals.
rj::Document deserialize_json_string_to_dom(const string &json)
Deserialize input string.
vrange deserialize_json_array_object_field_n(const string jdata, const string afield, const string field1, const string field2, const bool verbosep=true)
Deserialize json array, extract specific fields from array objects, return as vec of point_2t.