Loading...
Searching...
No Matches
json.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 Artificial Intelligence Techniques, S.L. and Roberto López González
3
4#pragma once
5#ifndef OPENNN_JSON_H_
6#define OPENNN_JSON_H_
7
8#include <cstddef>
9#include <filesystem>
10#include <format>
11#include <initializer_list>
12#include <iterator>
13#include <stdexcept>
14#include <string>
15#include <string_view>
16#include <utility>
17#include <variant>
18#include <vector>
19
20namespace opennn
21{
22
23class Json
24{
25public:
26 using Array = std::vector<Json>;
27 using Object = std::vector<std::pair<std::string, Json>>;
28
29 enum class Kind { Null, Bool, Number, String, Array, Object };
30
31 static Json make_object();
32 static Json make_array();
33
34 Json() = default;
35 Json(bool new_value) : value(new_value) {}
36 template <typename Int, typename = std::enable_if_t<std::is_integral_v<Int> && !std::is_same_v<Int, bool>>>
37 Json(Int new_value) : value(double(new_value)) {}
38 Json(double new_value) : value(new_value) {}
39 Json(float new_value) : value(double(new_value)) {}
40 Json(const char* new_value) : value(std::string(new_value)) {}
41 Json(const std::string& new_value) : value(new_value) {}
42 Json(std::string_view new_value) : value(std::string(new_value)) {}
43
44 Kind get_kind() const noexcept { return Kind(value.index()); }
45 bool is_null() const noexcept { return std::holds_alternative<std::monostate>(value); }
46 bool is_bool() const noexcept { return std::holds_alternative<bool>(value); }
47 bool is_number() const noexcept { return std::holds_alternative<double>(value); }
48 bool is_string() const noexcept { return std::holds_alternative<std::string>(value); }
49 bool is_array() const noexcept { return std::holds_alternative<Array>(value); }
50 bool is_object() const noexcept { return std::holds_alternative<Object>(value); }
52 const Array& as_array() const;
54 const Object& as_object() const;
55 bool has(std::string_view key) const { return find(key) != nullptr; }
56 const Json* find(std::string_view) const;
57 const Json& at(std::string_view) const;
58 Json& operator[](std::string_view);
59 Json& set(std::string_view, Json);
61 std::string as_string() const;
62 long long as_long() const;
63 double as_double() const;
64 bool as_bool() const;
65 static Json parse(std::string_view);
66 std::string dump(int indent = 2) const;
67
68private:
69 using Value = std::variant<std::monostate, bool, double, std::string, Array, Object>;
70
71 Value value;
72};
73
75{
76public:
77 static JsonDocument wrap(std::string_view, Json);
78
79 void load(const std::filesystem::path&);
80 void save(const std::filesystem::path&, int indent = 2) const;
81 void set_root(Json new_root) { root = std::move(new_root); }
82 Json& get_root() noexcept { return root; }
83 const Json& get_root() const noexcept { return root; }
84 const Json* first_child(std::string_view name) const { return root.find(name); }
85 const Json* first_child() const noexcept { return &root; }
86
87private:
88 Json root;
89};
90
92{
93public:
94 void open_element(std::string_view);
95 void close_element() { pop_scope(); }
96
97 void begin_array(std::string_view);
98 void end_array() { pop_scope(); }
100 void end_array_object() { pop_scope(); }
101 void add_field(std::string_view, Json);
102
103 template <typename Value>
104 void add_field(std::string_view name, Value&& value)
105 {
106 add_field(name, Json(std::forward<Value>(value)));
107 }
108
109 std::string c_str(int indent = 2) const { return root.dump(indent); }
110
111private:
112 void pop_scope();
113
114 Json root;
115 std::vector<Json*> stack;
116};
117template <typename Value>
118void add_json_field(JsonWriter& writer, std::string_view name, Value&& value)
119{
120 writer.add_field(name, std::forward<Value>(value));
121}
122
123void save_json_file(const std::filesystem::path&, const JsonWriter&);
124
125template <typename Serializable>
126void save_json_file(const std::filesystem::path& file_name, const Serializable& serializable)
127{
128 JsonWriter writer;
129 serializable.to_JSON(writer);
130 save_json_file(file_name, writer);
131}
132
134 std::initializer_list<std::pair<const char*, Json>>);
135float read_json_float (const Json*, std::string_view);
136long long read_json_index (const Json*, std::string_view);
137bool read_json_bool (const Json*, std::string_view);
138std::string read_json_string (const Json*, std::string_view);
139std::vector<std::string> read_json_strings(const Json*, std::string_view);
140
141float read_json_float (const Json*, std::string_view, float fallback);
142long long read_json_index (const Json*, std::string_view, long long fallback);
143bool read_json_bool (const Json*, std::string_view, bool fallback);
144std::string read_json_string(const Json*, std::string_view, std::string_view fallback);
145
147 std::initializer_list<std::string_view>);
148
149const Json* require_json_field(const Json*, std::string_view);
150
151template <typename Range>
152Json json_array(const Range& values)
153{
155 if constexpr (requires { std::size(values); })
156 array.as_array().reserve(std::size(values));
157 for (const auto& value : values)
158 array.push_back(Json(value));
159 return array;
160}
161
162template<typename Func>
163void for_json_items(const Json* parent, const char* tag, std::size_t count, Func func)
164{
165 if (!parent || !parent->is_object())
166 throw std::runtime_error(std::format("Missing JSON parent for: {}", tag));
167
168 const Json* const arr = parent->find(tag);
169 if (!arr || !arr->is_array() || arr->as_array().size() != count)
170 throw std::runtime_error(std::format("Missing or wrong-size JSON array: {}", tag));
171
172 for (std::size_t i = 0; i < count; ++i)
173 func(i, &arr->as_array()[i]);
174}
175
176JsonDocument load_json_file(const std::filesystem::path&);
177const Json* get_json_root (const JsonDocument&, std::string_view);
178
179}
180
181#endif
Definition json.h:75
void set_root(Json new_root)
Definition json.h:81
const Json & get_root() const noexcept
Definition json.h:83
void save(const std::filesystem::path &, int indent=2) const
void load(const std::filesystem::path &)
const Json * first_child(std::string_view name) const
Definition json.h:84
static JsonDocument wrap(std::string_view, Json)
const Json * first_child() const noexcept
Definition json.h:85
Json & get_root() noexcept
Definition json.h:82
Definition json.h:92
void end_array()
Definition json.h:98
void close_element()
Definition json.h:95
void add_field(std::string_view, Json)
void end_array_object()
Definition json.h:100
void begin_array(std::string_view)
void add_field(std::string_view name, Value &&value)
Definition json.h:104
void open_element(std::string_view)
std::string c_str(int indent=2) const
Definition json.h:109
Definition json.h:24
const Json & at(std::string_view) const
Array & as_array()
static Json parse(std::string_view)
Json(const std::string &new_value)
Definition json.h:41
Json & operator[](std::string_view)
static Json make_array()
bool is_array() const noexcept
Definition json.h:49
Json(bool new_value)
Definition json.h:35
Json(std::string_view new_value)
Definition json.h:42
bool has(std::string_view key) const
Definition json.h:55
bool is_null() const noexcept
Definition json.h:45
bool is_bool() const noexcept
Definition json.h:46
bool is_number() const noexcept
Definition json.h:47
std::string dump(int indent=2) const
long long as_long() const
Json(double new_value)
Definition json.h:38
Json(Int new_value)
Definition json.h:37
Object & as_object()
bool is_object() const noexcept
Definition json.h:50
const Json * find(std::string_view) const
double as_double() const
bool as_bool() const
std::vector< std::pair< std::string, Json > > Object
Definition json.h:27
Kind get_kind() const noexcept
Definition json.h:44
bool is_string() const noexcept
Definition json.h:48
Json(float new_value)
Definition json.h:39
static Json make_object()
const Object & as_object() const
Json(const char *new_value)
Definition json.h:40
void push_back(Json)
std::vector< Json > Array
Definition json.h:26
Json & set(std::string_view, Json)
std::string as_string() const
Kind
Definition json.h:29
@ String
Definition json.h:29
@ Number
Definition json.h:29
@ Null
Definition json.h:29
@ Bool
Definition json.h:29
Json()=default
const Array & as_array() const
Definition configuration.h:10
Json json_array(const Range &values)
Definition json.h:152
std::string read_json_string_fallback(const Json *, std::initializer_list< std::string_view >)
void write_json(JsonWriter &, std::initializer_list< std::pair< const char *, Json > >)
void for_json_items(const Json *parent, const char *tag, std::size_t count, Func func)
Definition json.h:163
void add_json_field(JsonWriter &writer, std::string_view name, Value &&value)
Definition json.h:118
Eigen::array< T, N > array
Definition tensor_types.h:736
bool read_json_bool(const Json *, std::string_view)
std::string read_json_string(const Json *, std::string_view)
std::vector< std::string > read_json_strings(const Json *, std::string_view)
long long read_json_index(const Json *, std::string_view)
const Json * get_json_root(const JsonDocument &, std::string_view)
void save_json_file(const std::filesystem::path &, const JsonWriter &)
const Json * require_json_field(const Json *, std::string_view)
JsonDocument load_json_file(const std::filesystem::path &)
float read_json_float(const Json *, std::string_view)