Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONParser.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Carsten D. Burgard, DESY/ATLAS, Dec 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13#include "JSONParser.h"
14
15#include <sstream>
16
17#include <nlohmann/json.hpp>
18
19// TJSONTree methods
20
21TJSONTree::TJSONTree() : root(this){};
22
23TJSONTree::TJSONTree(std::istream &is) : root(this, is){};
24
26{
28};
29
31{
32 _nodecache.push_back(n);
33 return _nodecache.back();
34}
35
37{
38 return *node;
39}
40
42{
43 return *node;
44}
45
47{
49}
50
51// TJSONTree::Node implementation
52
54public:
55 std::string _key;
56 std::string const &key() const { return _key; }
57 virtual nlohmann::json &get() = 0;
58 virtual const nlohmann::json &get() const = 0;
59 class BaseNode;
60 class NodeRef;
61 Impl(const std::string &k) : _key(k) {}
62 virtual ~Impl() = default;
63 static TJSONTree::Node &mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n);
64 static const TJSONTree::Node &mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n);
65};
66
69
70public:
71 nlohmann::json &get() override { return node; }
72 const nlohmann::json &get() const override { return node; }
73 BaseNode(std::istream &is) : Impl(""), node(nlohmann::json::parse(is)) {}
74 BaseNode() : Impl("") {}
75};
76
79
80public:
81 nlohmann::json &get() override { return node; }
82 const nlohmann::json &get() const override { return node; }
83 NodeRef(const std::string &k, nlohmann::json &n) : Impl(k), node(n) {}
84 NodeRef(const NodeRef &other) : Impl(other.key()), node(other.node) {}
85};
86
88{
89 Node::Impl::NodeRef ref(k, n);
90 return t->incache(Node(t, ref));
91}
92
93const TJSONTree::Node &TJSONTree::Node::Impl::mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n)
94{
95 // not so nice to use const_cast here, but the non-const version will only live in the cache
96 Node::Impl::NodeRef ref(k, const_cast<nlohmann::json &>(n));
97 return const_cast<TJSONTree *>(t)->incache(Node(const_cast<TJSONTree *>(t), ref));
98}
99
100TJSONTree::Node::Node(TJSONTree *t, std::istream &is) : tree(t), node(std::make_unique<Impl::BaseNode>(is)) {}
101
102TJSONTree::Node::Node(TJSONTree *t) : tree(t), node(std::make_unique<Impl::BaseNode>()) {}
103
105 : tree(t), node(std::make_unique<Impl::NodeRef>(other.key(), other.get()))
106{
107}
108
109TJSONTree::Node::Node(const Node &other) : Node(other.tree, *other.node) {}
110
112
113// TJSONNode interface
114
115void TJSONTree::Node::writeJSON(std::ostream &os) const
116{
117 os << node->get();
118}
119
121{
122 node->get() = s;
123 return *this;
124}
125
127{
128 node->get() = i;
129 return *this;
130}
131
133{
134 node->get() = d;
135 return *this;
136}
137
139{
140 node->get() = b;
141 return *this;
142}
143
145{
146 v = node->get().get<std::string>();
147 return *this;
148}
149
151{
152 return Impl::mkNode(tree, k, node->get()[k]);
153}
154
155const TJSONTree::Node &TJSONTree::Node::operator[](std::string const &k) const
156{
157 return Impl::mkNode(tree, k, node->get()[k]);
158}
159
161{
162 return node->get().is_array() || node->get().is_object();
163}
164
166{
167 return node->get().is_object();
168}
169
171{
172 return node->get().is_array();
173}
174
175namespace {
176
177// To check whether it's allowed to reset the type of an object. We allow
178// this for nodes that have no type yet, or nodes with an empty string.
179bool isResettingPossible(nlohmann::json const &node)
180{
181
182 if (node.type() == nlohmann::json::value_t::null) {
183 return true;
184 }
185
186 if (node.type() == nlohmann::json::value_t::string) {
187 if (node.get<std::string>() == "") {
188 return true;
189 }
190 }
191 return false;
192}
193} // namespace
194
196{
197 if (node->get().type() == nlohmann::json::value_t::object)
198 return *this;
199
200 if (isResettingPossible(node->get())) {
201 node->get() = nlohmann::json::object();
202 } else {
203 throw std::runtime_error("cannot declare " + this->key() + " to be of map-type, already of type " +
204 node->get().type_name());
205 }
206 return *this;
207}
208
210{
211 if (node->get().type() == nlohmann::json::value_t::array)
212 return *this;
213
214 if (isResettingPossible(node->get())) {
215 node->get() = nlohmann::json::array();
216 } else {
217 throw std::runtime_error("cannot declare " + this->key() + " to be of seq-type, already of type " +
218 node->get().type_name());
219 }
220 return *this;
221}
222
224{
225 node->get().clear();
226}
227
228std::string TJSONTree::Node::key() const
229{
230 return node->key();
231}
232
233std::string TJSONTree::Node::val() const
234{
235 switch (node->get().type()) {
236 case nlohmann::json::value_t::string: return node->get().get<std::string>();
237 case nlohmann::json::value_t::boolean: return node->get().get<bool>() ? "true" : "false";
238 case nlohmann::json::value_t::number_integer: return std::to_string(node->get().get<int>());
239 case nlohmann::json::value_t::number_unsigned: return std::to_string(node->get().get<unsigned int>());
240 case nlohmann::json::value_t::number_float: return std::to_string(node->get().get<double>());
241 default:
242 throw std::runtime_error(std::string("node " + node->key() + ": implicit string conversion for type " +
243 node->get().type_name() + " not supported!"));
244 }
245}
246
248{
249 return node->get().get<int>();
250}
252{
253 return node->get().get<double>();
254}
256{
257 auto const &nd = node->get();
258
259 // Attempting to convert zeroes and ones to bools.
260 if (nd.type() == nlohmann::json::value_t::number_unsigned) {
261 auto val = nd.get<unsigned int>();
262 if (val == 0)
263 return false;
264 if (val == 1)
265 return true;
266 }
267
268 return nd.get<bool>();
269}
270
272{
273 return !node->key().empty();
274}
275
277{
278 return node->get().is_primitive();
279}
280
281bool TJSONTree::Node::has_child(std::string const &c) const
282{
283 return node->get().find(c) != node->get().end();
284}
285
287{
288 node->get().push_back("");
289 return Impl::mkNode(tree, "", node->get().back());
290}
291
293{
294 return node->get().size();
295}
296
298{
299 return Impl::mkNode(tree, "", node->get().at(pos));
300}
301
303{
304 return Impl::mkNode(tree, "", node->get().at(pos));
305}
306
309
310template <class Nd, class NdType, class json_it>
312public:
313 enum class POS { BEGIN, END };
314 ChildItImpl(NdType &n, POS p)
315 : node(n), iter(p == POS::BEGIN ? n.get_node().get().begin() : n.get_node().get().end()){};
316 ChildItImpl(NdType &n, json_it it) : node(n), iter(it) {}
317 ChildItImpl(const ChildItImpl &other) : node(other.node), iter(other.iter) {}
319 std::unique_ptr<typename child_iterator::Impl> clone() const override
320 {
321 return std::make_unique<ChildItImpl>(node, iter);
322 }
323 void forward() override { ++iter; }
324 void backward() override { --iter; }
325 Nd &current() override
326 {
327 if (node.is_seq()) {
328 return TJSONTree::Node::Impl::mkNode(node.get_tree(), "", iter.value());
329 } else {
330 return TJSONTree::Node::Impl::mkNode(node.get_tree(), iter.key(), iter.value());
331 }
332 }
333 bool equal(const typename child_iterator::Impl &other) const override
334 {
335 // We can use static_cast here because we never compare Iterators for
336 // different JSON node types.
337 auto it = static_cast<const ChildItImpl<Nd, NdType, json_it> *>(&other);
338 return it && it->iter == this->iter;
339 }
340
341private:
342 NdType &node;
343 json_it iter;
344};
345
347{
349 return {child_iterator(std::make_unique<childIt>(*this, childIt::POS::BEGIN)),
350 child_iterator(std::make_unique<childIt>(*this, childIt::POS::END))};
351}
353{
354 using childConstIt =
356 return {const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::BEGIN)),
357 const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::END))};
358}
nlohmann::json json
nlohmann::basic_json<>::const_iterator const_json_iterator
nlohmann::basic_json<>::iterator json_iterator
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
winID h TVirtualViewer3D TVirtualGLPainter p
JSONNode & get(std::string const &key)
std::unique_ptr< typename child_iterator::Impl > clone() const override
ChildItImpl(NdType &n, POS p)
ChildItImpl(const ChildItImpl &other)
bool equal(const typename child_iterator::Impl &other) const override
ChildItImpl(NdType &n, json_it it)
const nlohmann::json & get() const override
nlohmann::json & get() override
NodeRef(const std::string &k, nlohmann::json &n)
NodeRef(const NodeRef &other)
const nlohmann::json & get() const override
nlohmann::json & get() override
Impl(const std::string &k)
virtual const nlohmann::json & get() const =0
static TJSONTree::Node & mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n)
virtual nlohmann::json & get()=0
std::string const & key() const
virtual ~Impl()=default
bool is_container() const override
bool has_child(std::string const &) const override
bool val_bool() const override
Node & child(size_t pos) override
const Node & operator>>(std::string &v) const override
Node & operator[](std::string const &k) override
Node & append_child() override
void clear() override
size_t num_children() const override
std::string val() const override
void writeJSON(std::ostream &os) const override
bool has_key() const override
std::string key() const override
Node & set_map() override
double val_double() const override
bool is_seq() const override
std::unique_ptr< Impl > node
Definition JSONParser.h:31
Node & set_seq() override
bool has_val() const override
Node(TJSONTree *t, std::istream &is)
const Impl & get_node() const
bool is_map() const override
children_view children() override
Node & operator<<(std::string const &s) override
int val_int() const override
TJSONTree::Node & incache(const TJSONTree::Node &n)
std::list< Node > _nodecache
Definition JSONParser.h:78
void clearcache()
~TJSONTree() override
a class to store JSON values
const Int_t n
Definition legend1.C:16
basic_json<> json
Definition tree.py:1