2020-01-18 08:38:21 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
2023-11-15 08:03:07 +00:00
|
|
|
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
|
2020-01-18 08:38:21 +00:00
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 08:38:21 +00:00
|
|
|
*/
|
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
#include <AK/ByteString.h>
|
2020-02-14 20:41:10 +00:00
|
|
|
#include <AK/Forward.h>
|
2019-07-08 11:03:23 +00:00
|
|
|
#include <AK/Optional.h>
|
2023-11-15 08:03:07 +00:00
|
|
|
#include <AK/OwnPtr.h>
|
2019-08-07 19:28:07 +00:00
|
|
|
#include <AK/StringBuilder.h>
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2019-06-17 19:34:12 +00:00
|
|
|
namespace AK {
|
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
class JsonValue {
|
|
|
|
public:
|
|
|
|
enum class Type {
|
|
|
|
Null,
|
|
|
|
Bool,
|
2023-11-15 08:03:07 +00:00
|
|
|
Number,
|
2019-06-17 17:47:35 +00:00
|
|
|
String,
|
|
|
|
Array,
|
|
|
|
Object,
|
|
|
|
};
|
|
|
|
|
2021-11-15 00:46:51 +00:00
|
|
|
static ErrorOr<JsonValue> from_string(StringView);
|
2019-06-24 09:25:10 +00:00
|
|
|
|
2023-11-15 08:03:07 +00:00
|
|
|
JsonValue();
|
|
|
|
~JsonValue();
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(JsonValue const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue(JsonValue&&);
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue& operator=(JsonValue const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue& operator=(JsonValue&&);
|
|
|
|
|
2020-05-22 11:57:23 +00:00
|
|
|
JsonValue(int);
|
|
|
|
JsonValue(unsigned);
|
|
|
|
JsonValue(long);
|
|
|
|
JsonValue(long unsigned);
|
|
|
|
JsonValue(long long);
|
|
|
|
JsonValue(long long unsigned);
|
2019-10-29 15:36:50 +00:00
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue(double);
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(char const*);
|
2023-12-16 14:19:34 +00:00
|
|
|
JsonValue(ByteString const&);
|
2022-01-27 12:01:10 +00:00
|
|
|
JsonValue(StringView);
|
2022-12-08 16:03:39 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
requires(SameAs<RemoveCVReference<T>, bool>)
|
|
|
|
JsonValue(T value)
|
2023-11-15 08:03:07 +00:00
|
|
|
: m_value { static_cast<bool>(value) }
|
2022-12-08 16:03:39 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(JsonArray const&);
|
|
|
|
JsonValue(JsonObject const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2019-08-04 09:46:31 +00:00
|
|
|
JsonValue(JsonArray&&);
|
|
|
|
JsonValue(JsonObject&&);
|
|
|
|
|
2023-11-15 08:03:07 +00:00
|
|
|
JsonValue& operator=(JsonArray const&);
|
|
|
|
JsonValue& operator=(JsonObject const&);
|
|
|
|
|
|
|
|
JsonValue& operator=(JsonArray&&);
|
|
|
|
JsonValue& operator=(JsonObject&&);
|
2019-08-04 09:46:31 +00:00
|
|
|
|
2019-08-07 19:28:07 +00:00
|
|
|
template<typename Builder>
|
|
|
|
typename Builder::OutputType serialized() const;
|
|
|
|
template<typename Builder>
|
|
|
|
void serialize(Builder&) const;
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString as_string_or(ByteString const& alternative) const
|
2019-08-07 20:03:25 +00:00
|
|
|
{
|
|
|
|
if (is_string())
|
|
|
|
return as_string();
|
|
|
|
return alternative;
|
|
|
|
}
|
|
|
|
|
2024-01-06 20:49:17 +00:00
|
|
|
ByteString deprecated_to_byte_string() const
|
2019-06-24 12:25:45 +00:00
|
|
|
{
|
|
|
|
if (is_string())
|
|
|
|
return as_string();
|
2019-08-07 19:28:07 +00:00
|
|
|
return serialized<StringBuilder>();
|
2019-06-24 12:25:45 +00:00
|
|
|
}
|
|
|
|
|
2024-01-13 01:52:38 +00:00
|
|
|
Optional<int> get_int() const { return get_integer<int>(); }
|
|
|
|
Optional<i32> get_i32() const { return get_integer<i32>(); }
|
|
|
|
Optional<i64> get_i64() const { return get_integer<i64>(); }
|
2019-10-29 15:36:50 +00:00
|
|
|
|
2024-01-13 01:52:38 +00:00
|
|
|
Optional<unsigned> get_uint() const { return get_integer<unsigned>(); }
|
|
|
|
Optional<u32> get_u32() const { return get_integer<u32>(); }
|
|
|
|
Optional<u64> get_u64() const { return get_integer<u64>(); }
|
|
|
|
Optional<float> get_float_with_precision_loss() const { return get_number_with_precision_loss<float>(); }
|
|
|
|
Optional<double> get_double_with_precision_loss() const { return get_number_with_precision_loss<double>(); }
|
2022-02-27 00:31:36 +00:00
|
|
|
|
2024-01-13 01:52:38 +00:00
|
|
|
Optional<FlatPtr> get_addr() const
|
2021-07-21 17:57:05 +00:00
|
|
|
{
|
2024-01-27 10:04:13 +00:00
|
|
|
// Note: This makes the lambda dependent on the template parameter, which is necessary
|
|
|
|
// for the `if constexpr` to not evaluate both branches.
|
|
|
|
auto fn = [&]<typename T>() -> Optional<T> {
|
|
|
|
if constexpr (IsSame<T, u64>) {
|
|
|
|
return get_u64();
|
|
|
|
} else {
|
|
|
|
return get_u32();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return fn.operator()<FlatPtr>();
|
2021-07-21 17:57:05 +00:00
|
|
|
}
|
|
|
|
|
2024-01-13 01:52:38 +00:00
|
|
|
Optional<bool> get_bool() const
|
2019-07-18 06:18:39 +00:00
|
|
|
{
|
2019-10-29 15:36:50 +00:00
|
|
|
if (!is_bool())
|
2024-01-13 01:52:38 +00:00
|
|
|
return {};
|
2019-10-29 15:36:50 +00:00
|
|
|
return as_bool();
|
2019-07-18 06:18:39 +00:00
|
|
|
}
|
|
|
|
|
2021-12-15 13:47:26 +00:00
|
|
|
bool as_bool() const
|
2019-06-29 10:04:36 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.get<bool>();
|
2019-06-29 10:04:36 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 01:28:20 +00:00
|
|
|
ByteString const& as_string() const
|
2019-06-18 06:55:58 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.get<ByteString>();
|
2019-06-24 10:03:31 +00:00
|
|
|
}
|
|
|
|
|
2022-11-17 21:17:13 +00:00
|
|
|
JsonObject& as_object()
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return *m_value.get<NonnullOwnPtr<JsonObject>>();
|
2022-11-17 21:17:13 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonObject const& as_object() const
|
2019-06-24 10:03:31 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return *m_value.get<NonnullOwnPtr<JsonObject>>();
|
2019-06-24 10:03:31 +00:00
|
|
|
}
|
|
|
|
|
2022-11-17 21:17:13 +00:00
|
|
|
JsonArray& as_array()
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return *m_value.get<NonnullOwnPtr<JsonArray>>();
|
2022-11-17 21:17:13 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonArray const& as_array() const
|
2019-06-24 10:03:31 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return *m_value.get<NonnullOwnPtr<JsonArray>>();
|
2019-06-18 06:55:58 +00:00
|
|
|
}
|
|
|
|
|
2023-11-14 05:49:41 +00:00
|
|
|
Variant<u64, i64, double> as_number() const
|
2019-07-18 06:18:39 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.downcast<u64, i64, double>();
|
2019-07-18 06:18:39 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 19:28:07 +00:00
|
|
|
Type type() const
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.visit(
|
|
|
|
[](Empty const&) { return Type::Null; },
|
|
|
|
[](bool const&) { return Type::Bool; },
|
|
|
|
[](Arithmetic auto const&) { return Type::Number; },
|
|
|
|
[](ByteString const&) { return Type::String; },
|
|
|
|
[](NonnullOwnPtr<JsonArray> const&) { return Type::Array; },
|
|
|
|
[](NonnullOwnPtr<JsonObject> const&) { return Type::Object; });
|
2019-08-07 19:28:07 +00:00
|
|
|
}
|
2019-06-19 11:08:07 +00:00
|
|
|
|
2023-11-15 08:03:07 +00:00
|
|
|
bool is_null() const { return m_value.has<Empty>(); }
|
|
|
|
bool is_bool() const { return m_value.has<bool>(); }
|
|
|
|
bool is_string() const { return m_value.has<ByteString>(); }
|
|
|
|
bool is_array() const { return m_value.has<NonnullOwnPtr<JsonArray>>(); }
|
|
|
|
bool is_object() const { return m_value.has<NonnullOwnPtr<JsonObject>>(); }
|
2019-06-29 07:04:45 +00:00
|
|
|
bool is_number() const
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.visit(
|
|
|
|
[](bool const&) { return false; },
|
|
|
|
[]<Arithmetic U>(U const&) { return true; },
|
|
|
|
[](auto const&) { return false; });
|
2019-06-29 07:04:45 +00:00
|
|
|
}
|
2019-06-19 11:08:07 +00:00
|
|
|
|
2019-10-29 15:36:50 +00:00
|
|
|
template<typename T>
|
2024-01-13 01:52:38 +00:00
|
|
|
Optional<T> get_number_with_precision_loss() const
|
2019-06-19 11:08:07 +00:00
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.visit(
|
|
|
|
[](bool const&) { return Optional<T> {}; },
|
|
|
|
[]<Arithmetic U>(U const& value) { return Optional<T> { static_cast<T>(value) }; },
|
|
|
|
[](auto const&) { return Optional<T> {}; });
|
2019-06-19 11:08:07 +00:00
|
|
|
}
|
|
|
|
|
2022-12-21 16:07:14 +00:00
|
|
|
template<Integral T>
|
|
|
|
bool is_integer() const
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return get_integer<T>().has_value();
|
2022-12-21 16:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<Integral T>
|
|
|
|
T as_integer() const
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return get_integer<T>().value();
|
2022-12-21 16:07:14 +00:00
|
|
|
}
|
|
|
|
|
2024-01-13 01:52:38 +00:00
|
|
|
template<Integral T>
|
|
|
|
Optional<T> get_integer() const
|
|
|
|
{
|
2023-11-15 08:03:07 +00:00
|
|
|
return m_value.visit(
|
|
|
|
[](bool const&) { return Optional<T> {}; },
|
|
|
|
[]<Arithmetic U>(U const& value) -> Optional<T> {
|
|
|
|
if constexpr (Integral<U>) {
|
|
|
|
if (!is_within_range<T>(value))
|
|
|
|
return {};
|
|
|
|
return static_cast<T>(value);
|
|
|
|
} else {
|
|
|
|
// FIXME: Make is_within_range work with floating point numbers.
|
|
|
|
if (static_cast<U>(static_cast<T>(value)) != value)
|
|
|
|
return {};
|
|
|
|
return static_cast<T>(value);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[](auto const&) { return Optional<T> {}; });
|
2024-01-13 01:52:38 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
bool equals(JsonValue const& other) const;
|
2020-03-31 18:44:34 +00:00
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
private:
|
2023-11-15 08:03:07 +00:00
|
|
|
Variant<
|
|
|
|
Empty,
|
|
|
|
bool,
|
|
|
|
i64,
|
|
|
|
u64,
|
|
|
|
double,
|
|
|
|
ByteString,
|
|
|
|
NonnullOwnPtr<JsonArray>,
|
|
|
|
NonnullOwnPtr<JsonObject>>
|
|
|
|
m_value;
|
2019-06-17 17:47:35 +00:00
|
|
|
};
|
2019-06-17 19:34:12 +00:00
|
|
|
|
2020-10-13 16:34:27 +00:00
|
|
|
template<>
|
|
|
|
struct Formatter<JsonValue> : Formatter<StringView> {
|
2021-11-16 00:15:21 +00:00
|
|
|
ErrorOr<void> format(FormatBuilder& builder, JsonValue const& value)
|
2020-10-13 16:34:27 +00:00
|
|
|
{
|
2024-01-06 20:49:17 +00:00
|
|
|
return Formatter<StringView>::format(builder, value.serialized<StringBuilder>());
|
2020-10-13 16:34:27 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-06-17 19:34:12 +00:00
|
|
|
}
|
|
|
|
|
2022-11-26 11:18:30 +00:00
|
|
|
#if USING_AK_GLOBALLY
|
2019-06-17 19:34:12 +00:00
|
|
|
using AK::JsonValue;
|
2022-11-26 11:18:30 +00:00
|
|
|
#endif
|