djson v3.1.3
JSON parser
 
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1#pragma once
2#include <djson/error.hpp>
4#include <expected>
5#include <format>
6#include <memory>
7#include <span>
8#include <string>
9#include <utility>
10
11namespace dj {
13template <typename Type>
14concept NumericT = std::integral<Type> || std::floating_point<Type>;
15
17template <typename Type>
18concept StringyT = std::convertible_to<Type, std::string_view>;
19
21template <typename Type>
22concept GettableT = std::same_as<Type, bool> || NumericT<Type> || StringyT<Type>;
23
25template <typename Type>
26concept SettableT = std::same_as<Type, std::nullptr_t> || GettableT<Type>;
27
28class Json;
29
31using Result = std::expected<Json, Error>;
32
34enum class JsonType : std::int8_t { Null, Boolean, Number, String, Array, Object, COUNT_ };
35
38 enum : std::uint8_t {
39 None = 0,
41 SortKeys = 1 << 0,
45 NoSpaces = 1 << 2,
46 };
47};
48using SerializeFlags = decltype(std::to_underlying(SerializeFlag::None));
51
55 std::string_view indent{" "};
57 std::string_view newline{"\n"};
59};
60
62enum class ParseMode : std::int8_t {
64 Auto,
66 Strict,
68 Jsonc,
69};
70
71namespace detail {
72struct Value;
73class Parser;
74} // namespace detail
75
77class Json {
78 public:
79 using Type = JsonType;
80
81 Json() = default;
82 ~Json() = default;
83
84 Json(Json&&) = default;
85 auto operator=(Json&&) -> Json& = default;
86
87 Json(Json const& other);
88 auto operator=(Json const& other) -> Json&;
89
90 explicit(false) Json(std::nullptr_t) noexcept {}
91
92 template <SettableT Type>
93 explicit(false) Json(Type const& value) {
94 set(value);
95 }
96
101 [[nodiscard]] static auto parse(std::string_view text, ParseMode mode = ParseMode::Auto) -> Result;
106 [[nodiscard]] static auto from_file(std::string_view path, ParseMode mode = ParseMode::Auto) -> Result;
107
109 [[nodiscard]] static auto empty_array() -> Json const&;
111 [[nodiscard]] static auto empty_object() -> Json const&;
112
114 [[nodiscard]] auto get_type() const -> Type;
115
116 [[nodiscard]] auto is_null() const -> bool { return get_type() == Type::Null; }
117 [[nodiscard]] auto is_boolean() const -> bool { return get_type() == Type::Boolean; }
118 [[nodiscard]] auto is_number() const -> bool { return get_type() == Type::Number; }
119 [[nodiscard]] auto is_string() const -> bool { return get_type() == Type::String; }
120 [[nodiscard]] auto is_array() const -> bool { return get_type() == Type::Array; }
121 [[nodiscard]] auto is_object() const -> bool { return get_type() == Type::Object; }
122
123 [[nodiscard]] auto as_bool(bool fallback = {}) const -> bool;
124 [[nodiscard]] auto as_double(double fallback = {}) const -> double;
125 [[nodiscard]] auto as_u64(std::uint64_t fallback = {}) const -> std::uint64_t;
126 [[nodiscard]] auto as_i64(std::int64_t fallback = {}) const -> std::int64_t;
127
128 [[nodiscard]] auto as_string_view(std::string_view fallback = {}) const -> std::string_view;
129 [[nodiscard]] auto as_string(std::string_view const fallback = {}) const -> std::string { return std::string{as_string_view(fallback)}; }
130
131 template <NumericT Type>
132 [[nodiscard]] auto as_number(Type const fallback = {}) const -> Type {
133 if constexpr (std::signed_integral<Type>) {
134 return static_cast<Type>(as_i64(static_cast<std::int64_t>(fallback)));
135 } else if constexpr (std::unsigned_integral<Type>) {
136 return static_cast<Type>(as_u64(static_cast<std::uint64_t>(fallback)));
137 } else {
138 return static_cast<Type>(as_double(static_cast<double>(fallback)));
139 }
140 }
141
142 template <GettableT Type>
143 [[nodiscard]] auto as(Type const& fallback = {}) const -> Type {
144 if constexpr (std::same_as<Type, bool>) {
145 return as_bool(fallback);
146 } else if constexpr (NumericT<Type>) {
147 return as_number(fallback);
148 } else if constexpr (std::same_as<Type, std::string_view>) {
149 return as_string_view(fallback);
150 } else {
151 return as_string(fallback);
152 }
153 }
154
155 [[nodiscard]] auto as_array() const -> std::span<dj::Json const>;
156 [[nodiscard]] auto as_object() const -> StringTable<dj::Json> const&;
157
158 void set_null();
159 void set_boolean(bool value);
160 void set_string(std::string_view value);
161 void set_number(std::int64_t value);
162 void set_number(std::uint64_t value);
163 void set_number(double value);
164 void set_value(Json value);
165
166 template <NumericT Type>
167 void set_number(Type const value) {
168 if constexpr (std::signed_integral<Type>) {
169 set_number(static_cast<std::int64_t>(value));
170 } else if constexpr (std::unsigned_integral<Type>) {
171 set_number(static_cast<std::uint64_t>(value));
172 } else {
173 set_number(static_cast<double>(value));
174 }
175 }
176
177 template <SettableT Type>
178 void set(Type const& value) {
179 if constexpr (std::same_as<Type, std::nullptr_t>) {
180 set_null();
181 } else if constexpr (std::same_as<Type, bool>) {
182 set_boolean(value);
183 } else if constexpr (NumericT<Type>) {
184 set_number(value);
185 } else {
186 set_string(value);
187 }
188 }
189
191 void set_array();
194
199 auto push_back(Json value = {}) -> Json&;
205 auto insert_or_assign(std::string key, Json value) -> Json&;
206
210 [[nodiscard]] auto operator[](std::string_view key) const -> Json const&;
214 [[nodiscard]] auto operator[](std::string_view key) -> Json&;
215
219 [[nodiscard]] auto operator[](std::size_t index) const -> Json const&;
223 [[nodiscard]] auto operator[](std::size_t index) -> Json&;
224
228 [[nodiscard]] auto serialize(SerializeOptions const& options = {}) const -> std::string;
233 [[nodiscard]] auto to_file(std::string_view path, SerializeOptions const& options = {}) const -> bool;
234
235 friend void swap(Json& a, Json& b) noexcept { std::swap(a.m_value, b.m_value); }
236
237 explicit operator bool() const { return m_value != nullptr; }
238
239 private:
240 struct Serializer;
241
242 struct Deleter {
243 void operator()(detail::Value* ptr) const noexcept;
244 };
245
246 void ensure_impl();
247
248 std::unique_ptr<detail::Value, Deleter> m_value;
249
250 friend class detail::Parser;
251};
252
253[[nodiscard]] inline auto to_string(Json const& json, SerializeOptions const& options = {}) { return json.serialize(options); }
254
256[[nodiscard]] auto make_escaped(std::string_view text) -> std::string;
257
259template <GettableT Type>
260void from_json(Json const& json, Type& value, Type const fallback = {}) {
261 value = json.as<Type>(fallback);
262}
263
265template <SettableT Type>
266void to_json(Json& json, Type const& value) {
267 json.set(value);
268}
269} // namespace dj
270
272template <>
273struct std::formatter<dj::Json> {
274 template <typename FormatParseContext>
275 constexpr auto parse(FormatParseContext& pc) const {
276 return pc.begin();
277 }
278
279 static auto format(dj::Json const& json, std::format_context& fc) -> std::format_context::iterator;
280};
Library interface, represents a valid JSON value.
Definition json.hpp:77
auto as_double(double fallback={}) const -> double
auto as_i64(std::int64_t fallback={}) const -> std::int64_t
auto as_object() const -> StringTable< dj::Json > const &
auto is_boolean() const -> bool
Definition json.hpp:117
static auto from_file(std::string_view path, ParseMode mode=ParseMode::Auto) -> Result
Parse JSON from a file.
static auto parse(std::string_view text, ParseMode mode=ParseMode::Auto) -> Result
Parse JSON text.
auto as_array() const -> std::span< dj::Json const >
auto operator=(Json &&) -> Json &=default
JsonType Type
Definition json.hpp:79
auto as_u64(std::uint64_t fallback={}) const -> std::uint64_t
friend class detail::Parser
Definition json.hpp:250
auto operator[](std::string_view key) -> Json &
Obtain the value associated with the passed key.
void set_null()
void set(Type const &value)
Definition json.hpp:178
auto operator[](std::string_view key) const -> Json const &
Obtain the value associated with the passed key.
Json(Json &&)=default
auto is_number() const -> bool
Definition json.hpp:118
auto is_null() const -> bool
Definition json.hpp:116
auto serialize(SerializeOptions const &options={}) const -> std::string
Serialize value as a string.
void set_boolean(bool value)
friend void swap(Json &a, Json &b) noexcept
Definition json.hpp:235
Json(Json const &other)
auto to_file(std::string_view path, SerializeOptions const &options={}) const -> bool
Write serialized string to a file.
auto is_array() const -> bool
Definition json.hpp:120
auto insert_or_assign(std::string key, Json value) -> Json &
Insert value associated with key into the Object. Converts to empty Object value first if not already...
auto as_number(Type const fallback={}) const -> Type
Definition json.hpp:132
auto as_bool(bool fallback={}) const -> bool
void set_value(Json value)
auto as_string(std::string_view const fallback={}) const -> std::string
Definition json.hpp:129
auto operator[](std::size_t index) -> Json &
Obtain the value at the passed index.
void set_array()
Set value to empty Array.
~Json()=default
auto operator=(Json const &other) -> Json &
void set_number(std::int64_t value)
void set_string(std::string_view value)
auto get_type() const -> Type
Obtain the value type of this Json.
static auto empty_array() -> Json const &
Obtain a Json representing an empty Array value.
auto as_string_view(std::string_view fallback={}) const -> std::string_view
static auto empty_object() -> Json const &
Obtain a Json representing an empty Object value.
auto operator[](std::size_t index) const -> Json const &
Obtain the value at the passed index.
auto is_object() const -> bool
Definition json.hpp:121
auto push_back(Json value={}) -> Json &
Insert value at the end of the Array. Converts to empty Array value first if not already one.
Json()=default
void set_object()
Set value to empty Object.
auto as(Type const &fallback={}) const -> Type
Definition json.hpp:143
auto is_string() const -> bool
Definition json.hpp:119
Type to obtain JSON value as.
Definition json.hpp:22
Numeric type.
Definition json.hpp:14
Type to set JSON value to.
Definition json.hpp:26
Stringy type.
Definition json.hpp:18
Definition error.hpp:5
decltype(std::to_underlying(SerializeFlag::None)) SerializeFlags
Definition json.hpp:48
auto to_string(Error const &error) -> std::string
Obtain print-friendly error string.
ParseMode
Parse mode.
Definition json.hpp:62
@ Auto
Automatic: Strict unless first line specifies JSONC mode.
@ Jsonc
Allow JSONC extensions.
@ Strict
Core JSON only.
void from_json(Json const &json, Type &value, Type const fallback={})
Assign JSON as value.
Definition json.hpp:260
constexpr auto serialize_flags_v
Default serialize flags.
Definition json.hpp:50
void to_json(Json &json, Type const &value)
Assign value to JSON.
Definition json.hpp:266
JsonType
JSON value type.
Definition json.hpp:34
std::expected< Json, Error > Result
Parse result type.
Definition json.hpp:31
auto make_escaped(std::string_view text) -> std::string
Convert input text to escaped string.
std::unordered_map< std::string, Value, StringHash, std::equal_to<> > StringTable
Heterogeneous string map.
Definition string_table.hpp:13
Bit flags for serialization options.
Definition json.hpp:37
@ None
Definition json.hpp:39
@ TrailingNewline
Append newline at the end. Ignored if NoSpaces is set.
Definition json.hpp:43
@ NoSpaces
No whitespace. Ignores TrailingNewLine and other whitespace options.
Definition json.hpp:45
@ SortKeys
Sort keys lexicographically.
Definition json.hpp:41
Serialization options.
Definition json.hpp:53
std::string_view indent
Indentation string. Ignored if SerializeFlag::NoSpaces is set.
Definition json.hpp:55
std::string_view newline
Newline string. Ignored if SerializeFlag::NoSpaces is set.
Definition json.hpp:57
SerializeFlags flags
Definition json.hpp:58
constexpr auto parse(FormatParseContext &pc) const
Definition json.hpp:275
static auto format(dj::Json const &json, std::format_context &fc) -> std::format_context::iterator