Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
19namespace {
20inline nlohmann::json parseWrapper(std::istream &is)
21{
22 try {
23 return nlohmann::json::parse(is);
24 } catch (const nlohmann::json::exception &ex) {
25 throw std::runtime_error(ex.what());
26 }
27}
28} // namespace
29
30// TJSONTree methods
31
33
34TJSONTree::TJSONTree(std::istream &is) : root(this, is){};
35
40
42{
43 _nodecache.push_back(n);
44 return _nodecache.back();
45}
46
48{
49 return *node;
50}
51
56
61
62// TJSONTree::Node implementation
63
65public:
66 std::string _key;
67 std::string const &key() const { return _key; }
68 virtual nlohmann::json &get() = 0;
69 virtual const nlohmann::json &get() const = 0;
70 class BaseNode;
71 class NodeRef;
72 Impl(const std::string &k) : _key(k) {}
73 virtual ~Impl() = default;
74 static TJSONTree::Node &mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n);
75 static const TJSONTree::Node &mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n);
76};
77
79 nlohmann::json node;
80
81public:
82 nlohmann::json &get() override { return node; }
83 const nlohmann::json &get() const override { return node; }
84 BaseNode(std::istream &is) : Impl(""), node(parseWrapper(is)) {}
85 BaseNode() : Impl("") {}
86};
87
89 nlohmann::json &node;
90
91public:
92 nlohmann::json &get() override { return node; }
93 const nlohmann::json &get() const override { return node; }
94 NodeRef(const std::string &k, nlohmann::json &n) : Impl(k), node(n) {}
96};
97
98TJSONTree::Node &TJSONTree::Node::Impl::mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n)
99{
100 Node::Impl::NodeRef ref(k, n);
101 return t->incache(Node(t, ref));
102}
103
104const TJSONTree::Node &TJSONTree::Node::Impl::mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n)
105{
106 // not so nice to use const_cast here, but the non-const version will only live in the cache
107 Node::Impl::NodeRef ref(k, const_cast<nlohmann::json &>(n));
108 return const_cast<TJSONTree *>(t)->incache(Node(const_cast<TJSONTree *>(t), ref));
109}
110
111TJSONTree::Node::Node(TJSONTree *t, std::istream &is) : tree(t), node(std::make_unique<Impl::BaseNode>(is)) {}
112
113TJSONTree::Node::Node(TJSONTree *t) : tree(t), node(std::make_unique<Impl::BaseNode>()) {}
114
116 : tree(t), node(std::make_unique<Impl::NodeRef>(other.key(), other.get()))
117{
118}
119
121
122TJSONTree::Node::~Node() = default;
123
124// TJSONNode interface
125
126void TJSONTree::Node::writeJSON(std::ostream &os) const
127{
128 os << node->get();
129}
130
132{
133 node->get() = s;
134 return *this;
135}
136
138{
139 node->get() = i;
140 return *this;
141}
142
144{
145 node->get() = d;
146 return *this;
147}
148
150{
151 node->get() = b;
152 return *this;
153}
154
156{
157 v = node->get().get<std::string>();
158 return *this;
159}
160
162{
163 return Impl::mkNode(tree, k, node->get()[k]);
164}
165
166const TJSONTree::Node &TJSONTree::Node::operator[](std::string const &k) const
167{
168 return Impl::mkNode(tree, k, node->get()[k]);
169}
170
172{
173 return node->get().is_array() || node->get().is_object();
174}
175
177{
178 return node->get().is_object();
179}
180
182{
183 return node->get().is_array();
184}
185
186namespace {
187
188// To check whether it's allowed to reset the type of an object. We allow
189// this for nodes that have no type yet, or nodes with an empty string.
190bool isResettingPossible(nlohmann::json const &node)
191{
192
193 if (node.type() == nlohmann::json::value_t::null) {
194 return true;
195 }
196
197 if (node.type() == nlohmann::json::value_t::string) {
198 if (node.get<std::string>().empty()) {
199 return true;
200 }
201 }
202 return false;
203}
204} // namespace
205
207{
208 if (node->get().type() == nlohmann::json::value_t::object)
209 return *this;
210
211 if (isResettingPossible(node->get())) {
212 node->get() = nlohmann::json::object();
213 } else {
214 throw std::runtime_error("cannot declare \"" + this->key() + "\" to be of map - type, already of type " +
215 node->get().type_name());
216 }
217 return *this;
218}
219
221{
222 if (node->get().type() == nlohmann::json::value_t::array)
223 return *this;
224
225 if (isResettingPossible(node->get())) {
226 node->get() = nlohmann::json::array();
227 } else {
228 throw std::runtime_error("cannot declare \"" + this->key() + "\" to be of seq - type, already of type " +
229 node->get().type_name());
230 }
231 return *this;
232}
233
235{
236 node->get().clear();
237}
238
239std::string TJSONTree::Node::key() const
240{
241 return node->key();
242}
243
244std::string TJSONTree::Node::val() const
245{
246 switch (node->get().type()) {
247 case nlohmann::json::value_t::string: return node->get().get<std::string>();
248 case nlohmann::json::value_t::boolean: return node->get().get<bool>() ? "true" : "false";
249 case nlohmann::json::value_t::number_integer: return std::to_string(node->get().get<int>());
250 case nlohmann::json::value_t::number_unsigned: return std::to_string(node->get().get<unsigned int>());
251 case nlohmann::json::value_t::number_float: return std::to_string(node->get().get<double>());
252 default:
253 throw std::runtime_error("node \"" + node->key() + "\": implicit string conversion for type " +
254 node->get().type_name() + " not supported!");
255 }
256}
257
259{
260 return node->get().get<int>();
261}
263{
264 return node->get().get<double>();
265}
267{
268 auto const &nd = node->get();
269
270 // Attempting to convert zeroes and ones to bools.
271 if (nd.type() == nlohmann::json::value_t::number_unsigned) {
272 auto val = nd.get<unsigned int>();
273 if (val == 0)
274 return false;
275 if (val == 1)
276 return true;
277 }
278
279 return nd.get<bool>();
280}
281
283{
284 return !node->key().empty();
285}
286
288{
289 return node->get().is_primitive();
290}
291
292bool TJSONTree::Node::has_child(std::string const &c) const
293{
294 return node->get().find(c) != node->get().end();
295}
296
298{
299 node->get().push_back("");
300 return Impl::mkNode(tree, "", node->get().back());
301}
302
304{
305 return node->get().size();
306}
307
309{
310 return Impl::mkNode(tree, "", node->get().at(pos));
311}
312
314{
315 return Impl::mkNode(tree, "", node->get().at(pos));
316}
317
320
321template <class Nd, class NdType, class json_it>
323public:
324 enum class POS { BEGIN, END };
326 : node(n), iter(p == POS::BEGIN ? n.get_node().get().begin() : n.get_node().get().end()){};
327 ChildItImpl(NdType &n, json_it it) : node(n), iter(it) {}
330 std::unique_ptr<typename child_iterator::Impl> clone() const override
331 {
332 return std::make_unique<ChildItImpl>(node, iter);
333 }
334 void forward() override { ++iter; }
335 void backward() override { --iter; }
336 Nd &current() override
337 {
338 if (node.is_seq()) {
339 return TJSONTree::Node::Impl::mkNode(node.get_tree(), "", iter.value());
340 } else {
341 return TJSONTree::Node::Impl::mkNode(node.get_tree(), iter.key(), iter.value());
342 }
343 }
344 bool equal(const typename child_iterator::Impl &other) const override
345 {
346 // We can use static_cast here because we never compare Iterators for
347 // different JSON node types.
348 auto it = static_cast<const ChildItImpl<Nd, NdType, json_it> *>(&other);
349 return it && it->iter == this->iter;
350 }
351
352private:
354 json_it iter;
355};
356
358{
360 return {child_iterator(std::make_unique<childIt>(*this, childIt::POS::BEGIN)),
361 child_iterator(std::make_unique<childIt>(*this, childIt::POS::END))};
362}
364{
365 using childConstIt =
367 return {const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::BEGIN)),
368 const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::END))};
369}
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
virtual ~Node()
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
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17