Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #include "json.h"
23 :
24 : #include <cmath>
25 : #include <cassert>
26 :
27 : #define PICOJSON_USE_LOCALE 1
28 : #define PICOJSON_ASSERT assert
29 : #include "picojson.h"
30 :
31 : #include "log.h"
32 :
33 : using namespace muse;
34 :
35 : struct muse::JsonData
36 : {
37 : picojson::value val;
38 : };
39 :
40 800205 : static inline const picojson::value& val_const(const std::shared_ptr<JsonData>& d)
41 : {
42 800205 : return d->val;
43 : }
44 :
45 5225 : static inline picojson::value& val_mut(std::shared_ptr<JsonData>& d)
46 : {
47 5225 : return d->val;
48 : }
49 :
50 : // =======================================
51 : // JsonValue
52 : // =======================================
53 106 : JsonValue::JsonValue(bool v)
54 106 : : m_data(std::make_shared<JsonData>())
55 : {
56 106 : val_mut(m_data).set<bool>(v);
57 106 : }
58 :
59 5102 : JsonValue::JsonValue(int v)
60 5102 : : m_data(std::make_shared<JsonData>())
61 : {
62 5102 : double d = static_cast<double>(v);
63 5102 : val_mut(m_data).set<double>(d);
64 5102 : }
65 :
66 0 : JsonValue::JsonValue(double v)
67 0 : : m_data(std::make_shared<JsonData>())
68 : {
69 0 : val_mut(m_data).set<double>(v);
70 0 : }
71 :
72 0 : JsonValue::JsonValue(const String& v)
73 0 : : m_data(std::make_shared<JsonData>())
74 : {
75 0 : val_mut(m_data).set<std::string>(v.toStdString());
76 0 : }
77 :
78 17 : JsonValue::JsonValue(const std::string& v)
79 17 : : m_data(std::make_shared<JsonData>())
80 : {
81 17 : val_mut(m_data).set<std::string>(v);
82 17 : }
83 :
84 0 : JsonValue::JsonValue(const char* v)
85 0 : : m_data(std::make_shared<JsonData>())
86 : {
87 0 : val_mut(m_data).set<std::string>(std::string(v));
88 0 : }
89 :
90 0 : JsonValue::JsonValue(const JsonArray& v)
91 0 : : m_data(v.m_data)
92 : {
93 0 : if (!m_data) {
94 0 : m_data = std::make_shared<JsonData>();
95 : }
96 0 : }
97 :
98 0 : JsonValue::JsonValue(const JsonObject& v)
99 0 : : m_data(v.m_data)
100 : {
101 0 : if (!m_data) {
102 0 : m_data = std::make_shared<JsonData>();
103 : }
104 0 : }
105 :
106 628933 : JsonValue::JsonValue(std::shared_ptr<JsonData> d)
107 628933 : : m_data(d)
108 : {
109 628933 : if (!m_data) {
110 276723 : m_data = std::make_shared<JsonData>();
111 : }
112 628933 : }
113 :
114 0 : void JsonValue::detach()
115 : {
116 0 : if (!m_data) {
117 0 : return;
118 : }
119 :
120 0 : if (m_data.use_count() == 1) {
121 0 : return;
122 : }
123 :
124 0 : m_data = std::make_shared<JsonData>(*m_data);
125 : }
126 :
127 4400 : bool JsonValue::isNull() const
128 : {
129 4400 : return val_const(m_data).is<picojson::null>();
130 : }
131 :
132 0 : void JsonValue::setNull()
133 : {
134 0 : detach();
135 0 : val_mut(m_data) = picojson::value();
136 0 : }
137 :
138 25 : bool JsonValue::isBool() const
139 : {
140 25 : return val_const(m_data).is<bool>();
141 : }
142 :
143 136 : bool JsonValue::toBool() const
144 : {
145 136 : return val_const(m_data).evaluate_as_boolean();
146 : }
147 :
148 0 : JsonValue& JsonValue::operator=(bool v)
149 : {
150 0 : detach();
151 0 : val_mut(m_data).set<bool>(v);
152 0 : return *this;
153 : }
154 :
155 125813 : bool JsonValue::isNumber() const
156 : {
157 125813 : return val_const(m_data).is<double>();
158 : }
159 :
160 100 : int JsonValue::toInt() const
161 : {
162 100 : if (!isNumber()) {
163 8 : return 0;
164 : }
165 92 : return static_cast<int>(std::round(val_const(m_data).get<double>()));
166 : }
167 :
168 125685 : double JsonValue::toDouble() const
169 : {
170 125685 : if (!isNumber()) {
171 32 : return 0.0;
172 : }
173 125653 : return val_const(m_data).get<double>();
174 : }
175 :
176 0 : JsonValue& JsonValue::operator=(int v)
177 : {
178 0 : detach();
179 0 : double d = static_cast<double>(v);
180 0 : val_mut(m_data).set<double>(d);
181 0 : return *this;
182 : }
183 :
184 0 : JsonValue& JsonValue::operator=(double v)
185 : {
186 0 : detach();
187 0 : val_mut(m_data).set<double>(v);
188 0 : return *this;
189 : }
190 :
191 109634 : bool JsonValue::isString() const
192 : {
193 109634 : return val_const(m_data).is<std::string>();
194 : }
195 :
196 102149 : String JsonValue::toString() const
197 : {
198 102149 : if (!isString()) {
199 47506 : static String dummy;
200 47506 : return dummy;
201 : }
202 54643 : return String::fromStdString(val_const(m_data).get<std::string>());
203 : }
204 :
205 7417 : const std::string& JsonValue::toStdString() const
206 : {
207 7417 : if (!isString()) {
208 8 : static std::string dummy;
209 8 : return dummy;
210 : }
211 7409 : return val_const(m_data).get<std::string>();
212 : }
213 :
214 0 : JsonValue& JsonValue::operator=(const String& str)
215 : {
216 0 : detach();
217 0 : val_mut(m_data).set<std::string>(str.toStdString());
218 0 : return *this;
219 : }
220 :
221 0 : JsonValue& JsonValue::operator=(const std::string& str)
222 : {
223 0 : detach();
224 0 : val_mut(m_data).set<std::string>(str);
225 0 : return *this;
226 : }
227 :
228 0 : JsonValue& JsonValue::operator=(const char* str)
229 : {
230 0 : detach();
231 0 : val_mut(m_data).set<std::string>(std::string(str));
232 0 : return *this;
233 : }
234 :
235 34 : bool JsonValue::isArray() const
236 : {
237 34 : return val_const(m_data).is<picojson::array>();
238 : }
239 :
240 65646 : JsonArray JsonValue::toArray() const
241 : {
242 65646 : return JsonArray(m_data);
243 : }
244 :
245 0 : JsonValue& JsonValue::operator=(const JsonArray& arr)
246 : {
247 0 : detach();
248 0 : val_mut(m_data) = val_const(arr.m_data);
249 0 : return *this;
250 : }
251 :
252 140 : bool JsonValue::isObject() const
253 : {
254 140 : return val_const(m_data).is<picojson::object>();
255 : }
256 :
257 104860 : JsonObject JsonValue::toObject() const
258 : {
259 104860 : return JsonObject(m_data);
260 : }
261 :
262 0 : JsonValue& JsonValue::operator=(const JsonObject& obj)
263 : {
264 0 : detach();
265 0 : val_mut(m_data) = val_const(obj.m_data);
266 0 : return *this;
267 : }
268 :
269 0 : Val JsonValue::toVal() const
270 : {
271 0 : if (isNull()) {
272 0 : return Val();
273 : }
274 0 : if (isBool()) {
275 0 : return Val(toBool());
276 : }
277 0 : if (isNumber()) {
278 0 : return Val(toDouble());
279 : }
280 0 : if (isString()) {
281 0 : return Val(toStdString());
282 : }
283 0 : if (isArray()) {
284 0 : muse::ValList list;
285 0 : const JsonArray array = toArray();
286 0 : for (size_t i = 0; i < array.size(); ++i) {
287 0 : list.emplace_back(array[i].toVal());
288 : }
289 0 : return Val(list);
290 0 : }
291 0 : if (isObject()) {
292 0 : muse::ValMap map;
293 0 : const JsonObject object = toObject();
294 0 : for (const auto& key : object.keys()) {
295 0 : map[key] = object[key].toVal();
296 0 : }
297 0 : return muse::Val(map);
298 0 : }
299 :
300 0 : return muse::Val();
301 : }
302 :
303 0 : JsonValue JsonValue::fromVal(const Val& val)
304 : {
305 0 : switch (val.type()) {
306 0 : case Val::Type::Undefined: return JsonValue();
307 0 : case Val::Type::Bool: return JsonValue(val.toBool());
308 0 : case Val::Type::Int: return JsonValue(val.toInt());
309 0 : case Val::Type::Int64: return JsonValue(val.toString()); // as string
310 0 : case Val::Type::Double: return JsonValue(val.toDouble());
311 0 : case Val::Type::String: return JsonValue(val.toString());
312 0 : case Val::Type::List: {
313 0 : JsonArray array;
314 0 : for (const auto& item : val.toList()) {
315 0 : array.append(fromVal(item));
316 0 : }
317 0 : return array;
318 0 : }
319 0 : case Val::Type::Map: {
320 0 : JsonObject object;
321 0 : for (const auto& [key, value] : val.toMap()) {
322 0 : object[key] = fromVal(value);
323 0 : }
324 0 : return object;
325 0 : }
326 0 : default: {
327 0 : NOT_SUPPORTED << "data type: " << (int)val.type();
328 : }
329 : }
330 :
331 0 : return JsonValue();
332 : }
333 :
334 : // =======================================
335 : // JsonValueRef
336 : // =======================================
337 :
338 13330 : JsonValueRef::JsonValueRef(const std::string& key, JsonObject* o)
339 13330 : : m_key(key), m_object(o)
340 : {
341 13330 : }
342 :
343 0 : JsonValueRef::JsonValueRef(size_t i, JsonArray* a)
344 0 : : m_idx(i), m_array(a)
345 : {
346 0 : }
347 :
348 2505 : JsonValueRef& JsonValueRef::operator=(bool v)
349 : {
350 2505 : if (m_object) {
351 2505 : m_object->set(m_key, v);
352 0 : } else if (m_array) {
353 0 : m_array->set(m_idx, v);
354 : }
355 2505 : return *this;
356 : }
357 :
358 4628 : JsonValueRef& JsonValueRef::operator=(int v)
359 : {
360 4628 : if (m_object) {
361 4628 : m_object->set(m_key, v);
362 0 : } else if (m_array) {
363 0 : m_array->set(m_idx, v);
364 : }
365 4628 : return *this;
366 : }
367 :
368 1231 : JsonValueRef& JsonValueRef::operator=(double v)
369 : {
370 1231 : if (m_object) {
371 1231 : m_object->set(m_key, v);
372 0 : } else if (m_array) {
373 0 : m_array->set(m_idx, v);
374 : }
375 1231 : return *this;
376 : }
377 :
378 637 : JsonValueRef& JsonValueRef::operator=(const String& v)
379 : {
380 637 : if (m_object) {
381 637 : m_object->set(m_key, v);
382 0 : } else if (m_array) {
383 0 : m_array->set(m_idx, v);
384 : }
385 637 : return *this;
386 : }
387 :
388 952 : JsonValueRef& JsonValueRef::operator=(const std::string& v)
389 : {
390 952 : if (m_object) {
391 952 : m_object->set(m_key, v);
392 0 : } else if (m_array) {
393 0 : m_array->set(m_idx, v);
394 : }
395 952 : return *this;
396 : }
397 :
398 8 : JsonValueRef& JsonValueRef::operator=(const char* v)
399 : {
400 8 : if (m_object) {
401 8 : m_object->set(m_key, v);
402 0 : } else if (m_array) {
403 0 : m_array->set(m_idx, v);
404 : }
405 8 : return *this;
406 : }
407 :
408 1 : JsonValueRef& JsonValueRef::operator=(const JsonValue& v)
409 : {
410 1 : if (m_object) {
411 1 : m_object->set(m_key, v);
412 0 : } else if (m_array) {
413 0 : m_array->set(m_idx, v);
414 : }
415 1 : return *this;
416 : }
417 :
418 1715 : JsonValueRef& JsonValueRef::operator=(const JsonArray& v)
419 : {
420 1715 : if (m_object) {
421 1715 : m_object->set(m_key, v);
422 0 : } else if (m_array) {
423 0 : m_array->set(m_idx, v);
424 : }
425 1715 : return *this;
426 : }
427 :
428 1653 : JsonValueRef& JsonValueRef::operator=(const JsonObject& v)
429 : {
430 1653 : if (m_object) {
431 1653 : m_object->set(m_key, v);
432 0 : } else if (m_array) {
433 0 : m_array->set(m_idx, v);
434 : }
435 1653 : return *this;
436 : }
437 :
438 : // =======================================
439 : // JsonArray
440 : // =======================================
441 :
442 137272 : static inline const picojson::array& array_const(const std::shared_ptr<JsonData>& d)
443 : {
444 137272 : return d->val.get<picojson::array>();
445 : }
446 :
447 7744 : static inline picojson::array& array_mut(std::shared_ptr<JsonData>& d)
448 : {
449 7744 : return d->val.get<picojson::array>();
450 : }
451 :
452 66922 : JsonArray::JsonArray(std::shared_ptr<JsonData> d)
453 66922 : : m_data(d)
454 : {
455 66922 : if (!m_data) {
456 1195 : m_data = std::make_shared<JsonData>();
457 1195 : m_data->val = picojson::value(picojson::array());
458 : }
459 66922 : }
460 :
461 1120 : JsonArray::JsonArray(std::initializer_list<JsonValue> args)
462 : {
463 1120 : m_data = std::make_shared<JsonData>();
464 1120 : m_data->val = picojson::value(picojson::array());
465 :
466 1120 : array_mut(m_data).reserve(args.size());
467 6221 : for (const JsonValue& v : args) {
468 5101 : array_mut(m_data).push_back(v.m_data->val);
469 : }
470 1120 : }
471 :
472 1523 : void JsonArray::detach()
473 : {
474 1523 : if (!m_data) {
475 0 : return;
476 : }
477 :
478 1523 : if (m_data.use_count() == 1) {
479 1523 : return;
480 : }
481 :
482 0 : m_data = std::make_shared<JsonData>(*m_data);
483 : }
484 :
485 7805 : size_t JsonArray::size() const
486 : {
487 7805 : return array_const(m_data).size();
488 : }
489 :
490 0 : void JsonArray::resize(size_t i)
491 : {
492 0 : detach();
493 0 : array_mut(m_data).resize(i);
494 0 : }
495 :
496 18 : bool JsonArray::empty() const
497 : {
498 18 : return array_const(m_data).size() == 0;
499 : }
500 :
501 129449 : JsonValue JsonArray::at(size_t i) const
502 : {
503 129449 : std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
504 129449 : d->val = array_const(m_data).at(i);
505 258898 : return JsonValue(d);
506 129449 : }
507 :
508 0 : JsonArray& JsonArray::set(size_t i, bool v)
509 : {
510 0 : detach();
511 0 : array_mut(m_data)[i] = picojson::value(v);
512 0 : return *this;
513 : }
514 :
515 0 : JsonArray& JsonArray::set(size_t i, int v)
516 : {
517 0 : detach();
518 0 : array_mut(m_data)[i] = picojson::value(static_cast<double>(v));
519 0 : return *this;
520 : }
521 :
522 0 : JsonArray& JsonArray::set(size_t i, double v)
523 : {
524 0 : detach();
525 0 : array_mut(m_data)[i] = picojson::value(v);
526 0 : return *this;
527 : }
528 :
529 0 : JsonArray& JsonArray::set(size_t i, const String& str)
530 : {
531 0 : detach();
532 0 : array_mut(m_data)[i] = picojson::value(str.toStdString());
533 0 : return *this;
534 : }
535 :
536 0 : JsonArray& JsonArray::set(size_t i, const std::string& str)
537 : {
538 0 : detach();
539 0 : array_mut(m_data)[i] = picojson::value(str);
540 0 : return *this;
541 : }
542 :
543 0 : JsonArray& JsonArray::set(size_t i, const char* str)
544 : {
545 0 : detach();
546 0 : array_mut(m_data)[i] = picojson::value(std::string(str));
547 0 : return *this;
548 : }
549 :
550 0 : JsonArray& JsonArray::set(size_t i, const JsonValue& v)
551 : {
552 0 : detach();
553 0 : array_mut(m_data)[i] = v.m_data->val;
554 0 : return *this;
555 : }
556 :
557 0 : JsonArray& JsonArray::set(size_t i, const JsonArray& v)
558 : {
559 0 : detach();
560 0 : array_mut(m_data)[i] = v.m_data->val;
561 0 : return *this;
562 : }
563 :
564 0 : JsonArray& JsonArray::set(size_t i, const JsonObject& v)
565 : {
566 0 : detach();
567 0 : array_mut(m_data)[i] = v.m_data->val;
568 0 : return *this;
569 : }
570 :
571 0 : JsonArray& JsonArray::append(bool v)
572 : {
573 0 : detach();
574 0 : array_mut(m_data).push_back(picojson::value(v));
575 0 : return *this;
576 : }
577 :
578 4 : JsonArray& JsonArray::append(int v)
579 : {
580 4 : detach();
581 4 : array_mut(m_data).push_back(picojson::value(static_cast<double>(v)));
582 4 : return *this;
583 : }
584 :
585 0 : JsonArray& JsonArray::append(double v)
586 : {
587 0 : detach();
588 0 : array_mut(m_data).push_back(picojson::value(v));
589 0 : return *this;
590 : }
591 :
592 0 : JsonArray& JsonArray::append(const String& str)
593 : {
594 0 : detach();
595 0 : array_mut(m_data).push_back(picojson::value(str.toStdString()));
596 0 : return *this;
597 : }
598 :
599 0 : JsonArray& JsonArray::append(const std::string& str)
600 : {
601 0 : detach();
602 0 : array_mut(m_data).push_back(picojson::value(str));
603 0 : return *this;
604 : }
605 :
606 0 : JsonArray& JsonArray::append(const char* str)
607 : {
608 0 : detach();
609 0 : array_mut(m_data).push_back(picojson::value(std::string(str)));
610 0 : return *this;
611 : }
612 :
613 16 : JsonArray& JsonArray::append(const JsonValue& v)
614 : {
615 16 : detach();
616 16 : array_mut(m_data).push_back(val_const(v.m_data));
617 16 : return *this;
618 : }
619 :
620 476 : JsonArray& JsonArray::append(const JsonArray& v)
621 : {
622 476 : detach();
623 476 : array_mut(m_data).push_back(val_const(v.m_data));
624 476 : return *this;
625 : }
626 :
627 1027 : JsonArray& JsonArray::append(const JsonObject& v)
628 : {
629 1027 : detach();
630 1027 : array_mut(m_data).push_back(val_const(v.m_data));
631 1027 : return *this;
632 : }
633 :
634 0 : JsonValue JsonArray::operator [](size_t i) const
635 : {
636 0 : return at(i);
637 : }
638 :
639 0 : JsonValueRef JsonArray::operator [](size_t i)
640 : {
641 0 : return JsonValueRef(i, this);
642 : }
643 :
644 : // =======================================
645 : // JsonObject
646 : // =======================================
647 321559 : static const picojson::object& object_const(const std::shared_ptr<JsonData>& d)
648 : {
649 321559 : return d->val.get<picojson::object>();
650 : }
651 :
652 13686 : static picojson::object& object_mut(std::shared_ptr<JsonData>& d)
653 : {
654 13686 : return d->val.get<picojson::object>();
655 : }
656 :
657 107814 : JsonObject::JsonObject(std::shared_ptr<JsonData> d)
658 107814 : : m_data(d)
659 : {
660 107814 : if (!m_data) {
661 2792 : m_data = std::make_shared<JsonData>();
662 2792 : m_data->val = picojson::value(picojson::object());
663 : }
664 107814 : }
665 :
666 13686 : void JsonObject::detach()
667 : {
668 13686 : if (!m_data) {
669 0 : return;
670 : }
671 :
672 13686 : if (m_data.use_count() == 1) {
673 13686 : return;
674 : }
675 :
676 0 : m_data = std::make_shared<JsonData>(*m_data);
677 : }
678 :
679 370707 : bool JsonObject::isValid() const
680 : {
681 370707 : return val_const(m_data).is<picojson::object>();
682 : }
683 :
684 55 : bool JsonObject::empty() const
685 : {
686 55 : if (!isValid()) {
687 0 : return true;
688 : }
689 :
690 55 : return object_const(m_data).size() == 0;
691 : }
692 :
693 1 : size_t JsonObject::size() const
694 : {
695 1 : if (!isValid()) {
696 0 : return 0;
697 : }
698 :
699 1 : return object_const(m_data).size();
700 : }
701 :
702 8989 : bool JsonObject::contains(const std::string& key) const
703 : {
704 8989 : if (!isValid()) {
705 0 : return false;
706 : }
707 :
708 8989 : const picojson::object& o = object_const(m_data);
709 8989 : return o.find(key) != o.cend();
710 : }
711 :
712 272446 : JsonValue JsonObject::value(const std::string& key, JsonValue def) const
713 : {
714 272446 : if (!isValid()) {
715 0 : return def;
716 : }
717 :
718 272446 : const picojson::object& o = object_const(m_data);
719 272446 : auto it = o.find(key);
720 272446 : if (it != o.cend()) {
721 222761 : std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
722 222761 : d->val = it->second;
723 222761 : return JsonValue(d);
724 222761 : }
725 49685 : return def;
726 : }
727 :
728 2513 : JsonObject& JsonObject::set(const std::string& key, bool v)
729 : {
730 2513 : detach();
731 2513 : object_mut(m_data).insert_or_assign(key, picojson::value(v));
732 2513 : return *this;
733 : }
734 :
735 4652 : JsonObject& JsonObject::set(const std::string& key, int v)
736 : {
737 4652 : detach();
738 4652 : object_mut(m_data).insert_or_assign(key, picojson::value(static_cast<double>(v)));
739 4652 : return *this;
740 : }
741 :
742 1231 : JsonObject& JsonObject::set(const std::string& key, double v)
743 : {
744 1231 : detach();
745 1231 : object_mut(m_data).insert_or_assign(key, picojson::value(v));
746 1231 : return *this;
747 : }
748 :
749 1183 : JsonObject& JsonObject::set(const std::string& key, const std::string& v)
750 : {
751 1183 : detach();
752 1183 : object_mut(m_data).insert_or_assign(key, picojson::value(v));
753 1183 : return *this;
754 : }
755 :
756 8 : JsonObject& JsonObject::set(const std::string& key, const char* str)
757 : {
758 8 : detach();
759 16 : object_mut(m_data).insert_or_assign(key, picojson::value(std::string(str)));
760 8 : return *this;
761 : }
762 :
763 637 : JsonObject& JsonObject::set(const std::string& key, const String& str)
764 : {
765 637 : detach();
766 637 : object_mut(m_data).insert_or_assign(key, picojson::value(str.toStdString()));
767 637 : return *this;
768 : }
769 :
770 14 : JsonObject& JsonObject::set(const std::string& key, const JsonValue& v)
771 : {
772 14 : detach();
773 14 : object_mut(m_data).insert_or_assign(key, v.m_data->val);
774 14 : return *this;
775 : }
776 :
777 1730 : JsonObject& JsonObject::set(const std::string& key, const JsonArray& v)
778 : {
779 1730 : detach();
780 1730 : object_mut(m_data).insert_or_assign(key, v.m_data->val);
781 1730 : return *this;
782 : }
783 :
784 1718 : JsonObject& JsonObject::set(const std::string& key, const JsonObject& v)
785 : {
786 1718 : detach();
787 1718 : object_mut(m_data).insert_or_assign(key, v.m_data->val);
788 1718 : return *this;
789 : }
790 :
791 42 : JsonValue JsonObject::operator [](const std::string& key) const
792 : {
793 42 : return value(key);
794 : }
795 :
796 13330 : JsonValueRef JsonObject::operator [](const std::string& key)
797 : {
798 13330 : return JsonValueRef(key, this);
799 : }
800 :
801 40068 : std::vector<std::string> JsonObject::keys() const
802 : {
803 40068 : std::vector<std::string> result;
804 40068 : const picojson::object& o = object_const(m_data);
805 158566 : for (auto&& p : o) {
806 118498 : result.push_back(p.first);
807 : }
808 40068 : return result;
809 0 : }
810 :
811 : // =======================================
812 : // JsonDocument
813 : // =======================================
814 243 : JsonDocument::JsonDocument(std::shared_ptr<JsonData> d)
815 243 : : m_data(d)
816 : {
817 243 : }
818 :
819 28 : JsonDocument::JsonDocument(JsonObject o)
820 28 : : m_data(o.m_data)
821 : {
822 28 : }
823 :
824 86 : JsonDocument::JsonDocument(JsonArray a)
825 86 : : m_data(a.m_data)
826 : {
827 86 : }
828 :
829 114 : ByteArray JsonDocument::toJson(Format format) const
830 : {
831 114 : std::string json = m_data->val.serialize(format == Format::Indented);
832 228 : return ByteArray(json.c_str(), json.size());
833 114 : }
834 :
835 243 : JsonDocument JsonDocument::fromJson(const ByteArray& ba, std::string* err)
836 : {
837 243 : std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
838 :
839 243 : std::string_view json(ba.constChar(), ba.size());
840 :
841 243 : const char* currentLoc = setlocale(LC_NUMERIC, "C");
842 243 : picojson::parse(d->val, json.begin(), json.end(), err);
843 243 : setlocale(LC_NUMERIC, currentLoc);
844 :
845 243 : JsonDocument doc(d);
846 243 : return doc;
847 243 : }
848 :
849 10 : bool JsonDocument::isObject() const
850 : {
851 10 : return m_data->val.is<picojson::object>();
852 : }
853 :
854 80 : bool JsonDocument::isArray() const
855 : {
856 80 : return m_data->val.is<picojson::array>();
857 : }
858 :
859 162 : JsonObject JsonDocument::rootObject() const
860 : {
861 162 : return JsonObject(m_data);
862 : }
863 :
864 81 : JsonArray JsonDocument::rootArray() const
865 : {
866 81 : return JsonArray(m_data);
867 : }
|