From 56f5c14d86d8abafd798dde1138ff6bd01399fb8 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 27 Aug 2019 14:12:44 +0300 Subject: [PATCH] JSON: Add JSON serializers These are two new types that allow serializing JSON on-the-fly as it's generated, without building the whole JSON in memory first. --- AK/JsonArraySerializer.h | 65 +++++++++++++++++++++++++++++++++ AK/JsonObjectSerializer.h | 77 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 AK/JsonArraySerializer.h create mode 100644 AK/JsonObjectSerializer.h diff --git a/AK/JsonArraySerializer.h b/AK/JsonArraySerializer.h new file mode 100644 index 0000000000..46bbd14ac5 --- /dev/null +++ b/AK/JsonArraySerializer.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +namespace AK { + +template +class JsonObjectSerializer; + +template +class JsonArraySerializer { +public: + explicit JsonArraySerializer(Builder& builder) + : m_builder(builder) + { + m_builder.append('['); + } + + JsonArraySerializer(const JsonArraySerializer&) = delete; + JsonArraySerializer(JsonArraySerializer&&) = delete; + + ~JsonArraySerializer() + { + if (!m_finished) + finish(); + } + + void add(const JsonValue& value) + { + begin_item(); + value.serialize(m_builder); + } + + JsonArraySerializer add_array() + { + begin_item(); + return JsonArraySerializer(m_builder); + } + + // Implemented in JsonObjectSerializer.h + JsonObjectSerializer add_object(); + + void finish() + { + ASSERT(!m_finished); + m_finished = true; + m_builder.append(']'); + } + +private: + void begin_item() + { + if (!m_empty) + m_builder.append(','); + m_empty = false; + } + + Builder& m_builder; + bool m_empty { true }; + bool m_finished { false }; +}; + +} + +using AK::JsonArraySerializer; diff --git a/AK/JsonObjectSerializer.h b/AK/JsonObjectSerializer.h new file mode 100644 index 0000000000..1cdb7743fe --- /dev/null +++ b/AK/JsonObjectSerializer.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include + +namespace AK { + +template +class JsonObjectSerializer { +public: + explicit JsonObjectSerializer(Builder& builder) + : m_builder(builder) + { + m_builder.append('{'); + } + + JsonObjectSerializer(const JsonObjectSerializer&) = delete; + JsonObjectSerializer(JsonObjectSerializer&&) = delete; + + ~JsonObjectSerializer() + { + if (!m_finished) + finish(); + } + + void add(const StringView& key, const JsonValue& value) + { + begin_item(key); + value.serialize(m_builder); + } + + JsonArraySerializer add_array(const StringView& key) + { + begin_item(key); + return JsonArraySerializer(m_builder); + } + + JsonObjectSerializer add_object(const StringView& key) + { + begin_item(key); + return JsonObjectSerializer(m_builder); + } + + void finish() + { + ASSERT(!m_finished); + m_finished = true; + m_builder.append('}'); + } + +private: + void begin_item(const StringView& key) + { + if (!m_empty) + m_builder.append(','); + m_empty = false; + + m_builder.append('"'); + m_builder.append(key); + m_builder.append("\":"); + } + + Builder& m_builder; + bool m_empty { true }; + bool m_finished { false }; +}; + +template +JsonObjectSerializer JsonArraySerializer::add_object() +{ + begin_item(); + return JsonObjectSerializer(m_builder); +} + +} + +using AK::JsonObjectSerializer;