djson v3.1.6
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 // NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
39 enum : std::uint8_t {
40 None = 0,
42 SortKeys = 1 << 0,
46 NoSpaces = 1 << 2,
47 };
48};
49using SerializeFlags = decltype(std::to_underlying(SerializeFlag::None));
51inline constexpr auto serialize_flags_v =
53
57 std::string_view indent{" "};
59 std::string_view newline{"\n"};
61};
62
64enum class ParseMode : std::int8_t {
71};
72
73namespace detail {
74struct Value;
75class Parser;
76} // namespace detail
77
79class Json {
80 public:
81 using Type = JsonType;
82
83 Json() = default;
84 ~Json() = default;
85
86 Json(Json&&) = default;
87 auto operator=(Json&&) -> Json& = default;
88
89 Json(Json const& other);
90 auto operator=(Json const& other) -> Json&;
91
92 explicit(false) Json(std::nullptr_t) noexcept {}
93
94 template <SettableT Type>
95 explicit(false) Json(Type const& value) {
96 set(value);
97 }
98
103 [[nodiscard]] static auto parse(std::string_view text, ParseMode mode = ParseMode::Auto) -> Result;
108 [[nodiscard]] static auto from_file(std::string_view path, ParseMode mode = ParseMode::Auto) -> Result;
109
111 [[nodiscard]] static auto empty_array() -> Json const&;
113 [[nodiscard]] static auto empty_object() -> Json const&;
114
116 [[nodiscard]] auto get_type() const -> Type;
117
118 [[nodiscard]] auto is_null() const -> bool { return get_type() == Type::Null; }
119 [[nodiscard]] auto is_boolean() const -> bool { return get_type() == Type::Boolean; }
120 [[nodiscard]] auto is_number() const -> bool { return get_type() == Type::Number; }
121 [[nodiscard]] auto is_string() const -> bool { return get_type() == Type::String; }
122 [[nodiscard]] auto is_array() const -> bool { return get_type() == Type::Array; }
123 [[nodiscard]] auto is_object() const -> bool { return get_type() == Type::Object; }
124
125 [[nodiscard]] auto as_bool(bool fallback = {}) const -> bool;
126 [[nodiscard]] auto as_double(double fallback = {}) const -> double;
127 [[nodiscard]] auto as_u64(std::uint64_t fallback = {}) const -> std::uint64_t;
128 [[nodiscard]] auto as_i64(std::int64_t fallback = {}) const -> std::int64_t;
129
130 [[nodiscard]] auto as_string_view(std::string_view fallback = {}) const -> std::string_view;
131 [[nodiscard]] auto as_string(std::string_view const fallback = {}) const -> std::string {
132 return std::string{as_string_view(fallback)};
133 }
134
135 template <NumericT Type>
136 [[nodiscard]] auto as_number(Type const fallback = {}) const -> Type {
137 if constexpr (std::signed_integral<Type>) {
138 return static_cast<Type>(as_i64(static_cast<std::int64_t>(fallback)));
139 } else if constexpr (std::unsigned_integral<Type>) {
140 return static_cast<Type>(as_u64(static_cast<std::uint64_t>(fallback)));
141 } else {
142 return static_cast<Type>(as_double(static_cast<double>(fallback)));
143 }
144 }
145
146 template <GettableT Type>
147 [[nodiscard]] auto as(Type const& fallback = {}) const -> Type {
148 if constexpr (std::same_as<Type, bool>) {
149 return as_bool(fallback);
150 } else if constexpr (NumericT<Type>) {
151 return as_number(fallback);
152 } else if constexpr (std::same_as<Type, std::string_view>) {
153 return as_string_view(fallback);
154 } else {
155 return as_string(fallback);
156 }
157 }
158
159 [[nodiscard]] auto as_array() const -> std::span<dj::Json const>;
160 [[nodiscard]] auto as_object() const -> StringTable<dj::Json> const&;
161
162 void set_null();
163 void set_boolean(bool value);
164 void set_string(std::string_view value);
165 void set_number(std::int64_t value);
166 void set_number(std::uint64_t value);
167 void set_number(double value);
168 void set_value(Json value);
169
170 template <NumericT Type>
171 void set_number(Type const value) {
172 if constexpr (std::signed_integral<Type>) {
173 set_number(static_cast<std::int64_t>(value));
174 } else if constexpr (std::unsigned_integral<Type>) {
175 set_number(static_cast<std::uint64_t>(value));
176 } else {
177 set_number(static_cast<double>(value));
178 }
179 }
180
181 template <SettableT Type>
182 void set(Type const& value) {
183 if constexpr (std::same_as<Type, std::nullptr_t>) {
184 set_null();
185 } else if constexpr (std::same_as<Type, bool>) {
186 set_boolean(value);
187 } else if constexpr (NumericT<Type>) {
188 set_number(value);
189 } else {
190 set_string(value);
191 }
192 }
193
195 void set_array();
198
203 auto push_back(Json value = {}) -> Json&;
209 auto insert_or_assign(std::string key, Json value) -> Json&;
210
214 [[nodiscard]] auto at(std::string_view key) const -> Json const&;
218 [[nodiscard]] auto at(std::string_view key) -> Json&;
222 [[nodiscard]] auto at(std::size_t index) const -> Json const&;
226 [[nodiscard]] auto at(std::size_t index) -> Json&;
227
228 [[nodiscard]] auto& operator[](this auto&& self, std::string_view const key) { return self.at(key); }
229 [[nodiscard]] auto& operator[](this auto&& self, std::size_t const index) { return self.at(index); }
230
234 [[nodiscard]] auto serialize(SerializeOptions const& options = {}) const -> std::string;
239 [[nodiscard]] auto to_file(std::string_view path, SerializeOptions const& options = {}) const -> bool;
240
241 friend void swap(Json& a, Json& b) noexcept { std::swap(a.m_value, b.m_value); }
242
243 explicit operator bool() const { return m_value != nullptr; }
244
245 private:
246 struct Serializer;
247
248 struct Deleter {
249 void operator()(detail::Value* ptr) const noexcept;
250 };
251
252 void ensure_impl();
253
254 std::unique_ptr<detail::Value, Deleter> m_value;
255
256 friend class detail::Parser;
257};
258
259[[nodiscard]] inline auto to_string(Json const& json, SerializeOptions const& options = {}) {
260 return json.serialize(options);
261}
262
264[[nodiscard]] auto make_escaped(std::string_view text) -> std::string;
265
267template <GettableT Type>
268void from_json(Json const& json, Type& value, Type const fallback = {}) {
269 value = json.as<Type>(fallback);
270}
271
273template <SettableT Type>
274void to_json(Json& json, Type const& value) {
275 json.set(value);
276}
277} // namespace dj
278
280template <>
281struct std::formatter<dj::Json> {
282 template <typename FormatParseContext>
283 constexpr auto parse(FormatParseContext& pc) const {
284 return pc.begin();
285 }
286
287 static auto format(dj::Json const& json, std::format_context& fc) -> std::format_context::iterator;
288};
Library interface, represents a valid JSON value.
Definition json.hpp:79
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:119
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 at(std::size_t index) -> Json &
Obtain the value at the passed index.
auto operator=(Json &&) -> Json &=default
JsonType Type
Definition json.hpp:81
auto as_u64(std::uint64_t fallback={}) const -> std::uint64_t
friend class detail::Parser
Definition json.hpp:256
auto & operator[](this auto &&self, std::string_view const key)
Definition json.hpp:228
void set_null()
void set(Type const &value)
Definition json.hpp:182
Json(Json &&)=default
auto is_number() const -> bool
Definition json.hpp:120
auto is_null() const -> bool
Definition json.hpp:118
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:241
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:122
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:136
auto at(std::string_view key) -> Json &
Obtain the value associated with the passed key.
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:131
auto at(std::string_view key) const -> Json const &
Obtain the value associated with the passed key.
void set_array()
Set value to empty Array.
~Json()=default
auto & operator[](this auto &&self, std::size_t const index)
Definition json.hpp:229
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 at(std::size_t index) const -> Json const &
Obtain the value at the passed index.
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 is_object() const -> bool
Definition json.hpp:123
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:147
auto is_string() const -> bool
Definition json.hpp:121
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 json.hpp:73
Definition error.hpp:5
std::unordered_map< std::string, Value, StringHash, std::equal_to<> > StringTable
Heterogeneous string map.
Definition string_table.hpp:13
std::expected< Json, Error > Result
Parse result type.
Definition json.hpp:31
auto to_string(Error const &error) -> std::string
Obtain print-friendly error string.
ParseMode
Parse mode.
Definition json.hpp:64
@ Auto
Automatic: Strict unless first line specifies JSONC mode, or file extension is .jsonc.
Definition json.hpp:66
@ Jsonc
Allow JSONC extensions.
Definition json.hpp:70
@ Strict
Core JSON only.
Definition json.hpp:68
void from_json(Json const &json, Type &value, Type const fallback={})
Assign JSON as value.
Definition json.hpp:268
decltype(std::to_underlying(SerializeFlag::None)) SerializeFlags
Definition json.hpp:49
constexpr auto serialize_flags_v
Default serialize flags.
Definition json.hpp:51
void to_json(Json &json, Type const &value)
Assign value to JSON.
Definition json.hpp:274
JsonType
JSON value type.
Definition json.hpp:34
@ String
Definition json.hpp:34
@ Boolean
Definition json.hpp:34
@ Array
Definition json.hpp:34
@ Object
Definition json.hpp:34
@ COUNT_
Definition json.hpp:34
@ Number
Definition json.hpp:34
@ Null
Definition json.hpp:34
auto make_escaped(std::string_view text) -> std::string
Convert input text to escaped string.
Bit flags for serialization options.
Definition json.hpp:37
@ None
Definition json.hpp:40
@ TrailingNewline
Append newline at the end. Ignored if NoSpaces is set.
Definition json.hpp:44
@ NoSpaces
No whitespace. Ignores TrailingNewLine and other whitespace options.
Definition json.hpp:46
@ SortKeys
Sort keys lexicographically.
Definition json.hpp:42
Serialization options.
Definition json.hpp:55
std::string_view indent
Indentation string. Ignored if SerializeFlag::NoSpaces is set.
Definition json.hpp:57
std::string_view newline
Newline string. Ignored if SerializeFlag::NoSpaces is set.
Definition json.hpp:59
SerializeFlags flags
Definition json.hpp:60
constexpr auto parse(FormatParseContext &pc) const
Definition json.hpp:283
static auto format(dj::Json const &json, std::format_context &fc) -> std::format_context::iterator