[Serialization] Add Json serializer

This commit is contained in:
SweetId 2024-03-10 17:04:15 -04:00
parent c1f429e916
commit 6a6ffb6779
3 changed files with 188 additions and 2 deletions

View File

@ -0,0 +1,53 @@
#pragma once
#include <Nazara/Core/Export.hpp>
#include <Nazara/Core/Serialization.hpp>
namespace Nz
{
class NAZARA_CORE_API JsonSerializationContext
: public SerializationContext
{
public:
JsonSerializationContext();
~JsonSerializationContext();
bool Load(const std::filesystem::path& path);
EnumSerializationMode GetEnumSerializationMode() const override { return EnumSerializationMode::String; }
bool PushObject(std::string_view name) override;
bool PopObject() override;
bool PushArray(std::string_view name) override;
bool PopArray() override;
bool Write(std::string_view name, bool value) override;
bool Write(std::string_view name, Nz::Int8 value) override;
bool Write(std::string_view name, Nz::Int16 value) override;
bool Write(std::string_view name, Nz::Int32 value) override;
bool Write(std::string_view name, Nz::Int64 value) override;
bool Write(std::string_view name, Nz::UInt8 value) override;
bool Write(std::string_view name, Nz::UInt16 value) override;
bool Write(std::string_view name, Nz::UInt32 value) override;
bool Write(std::string_view name, Nz::UInt64 value) override;
bool Write(std::string_view name, float value) override;
bool Write(std::string_view name, double value) override;
bool Write(std::string_view name, const std::string& value) override;
bool Read(std::string_view name, bool* value) override;
bool Read(std::string_view name, Nz::Int8* value) override;
bool Read(std::string_view name, Nz::Int16* value) override;
bool Read(std::string_view name, Nz::Int32* value) override;
bool Read(std::string_view name, Nz::Int64* value) override;
bool Read(std::string_view name, Nz::UInt8* value) override;
bool Read(std::string_view name, Nz::UInt16* value) override;
bool Read(std::string_view name, Nz::UInt32* value) override;
bool Read(std::string_view name, Nz::UInt64* value) override;
bool Read(std::string_view name, float* value) override;
bool Read(std::string_view name, double* value) override;
bool Read(std::string_view name, std::string* value) override;
private:
std::unique_ptr<struct JsonImpl> m_impl;
};
}

View File

@ -0,0 +1,132 @@
#include <Nazara/Core/JsonSerialization.hpp>
#include <Nazara/Core/FilesystemAppComponent.hpp>
#include <Nazara/Core/ApplicationBase.hpp>
#include <nlohmann/json.hpp>
#include <stack>
namespace Nz
{
struct JsonImpl
{
nlohmann::json& Top() { return *stack.top(); }
bool Pop()
{
if (stack.empty())
{
NazaraAssert(stack.empty(), "Stack is empty");
return false;
}
stack.pop();
return true;
}
nlohmann::json json;
std::stack<nlohmann::json*> stack;
};
JsonSerializationContext::JsonSerializationContext()
: m_impl(std::make_unique<JsonImpl>())
{}
JsonSerializationContext::~JsonSerializationContext() {}
bool JsonSerializationContext::Load(const std::filesystem::path& path)
{
std::ifstream file(path);
if (!file || !file.is_open())
return false;
m_impl->json = nlohmann::json::parse(file);
m_impl->stack.push(&m_impl->json);
return true;
}
bool JsonSerializationContext::PushObject(std::string_view name)
{
if (name.empty()) // special case if name is empty, don't push
return true;
if (!m_impl->Top().contains(name))
return false;
if (!m_impl->Top()[name].is_object())
{
NazaraAssert(m_impl->Top()[name].is_object(), "Value is not an object");
return false;
}
m_impl->stack.push(&m_impl->Top()[name]);
return true;
}
bool JsonSerializationContext::PopObject()
{
return m_impl->Pop();
}
bool JsonSerializationContext::PushArray(std::string_view name)
{
if (!m_impl->Top()[name].is_array())
{
NazaraAssert(m_impl->Top()[name].is_array(), "Value is not an array");
return false;
}
m_impl->stack.push(&m_impl->Top()[name]);
return true;
}
bool JsonSerializationContext::PopArray()
{
return m_impl->Pop();
}
#define DEF_SERIALIZE(Type, cond) \
bool JsonSerializationContext::Write(std::string_view name, Type value) \
{ \
m_impl->Top()[name] = value; \
return true; \
} \
bool JsonSerializationContext::Read(std::string_view name, Type* value) \
{ \
if (!m_impl->Top()[name].cond()) \
{ \
/*NazaraAssert(m_impl->Top()[name].cond(), "Value failed check: " #cond "()");*/\
return false; \
} \
*value = m_impl->Top()[name].get<Type>(); \
return true; \
} \
DEF_SERIALIZE(bool, is_boolean);
DEF_SERIALIZE(Nz::Int8, is_number);
DEF_SERIALIZE(Nz::Int16, is_number);
DEF_SERIALIZE(Nz::Int32, is_number);
DEF_SERIALIZE(Nz::Int64, is_number);
DEF_SERIALIZE(Nz::UInt8, is_number);
DEF_SERIALIZE(Nz::UInt16, is_number);
DEF_SERIALIZE(Nz::UInt32, is_number);
DEF_SERIALIZE(Nz::UInt64, is_number);
DEF_SERIALIZE(float, is_number);
DEF_SERIALIZE(double, is_number);
#undef DEF_SERIALIZE
bool JsonSerializationContext::Write(std::string_view name, const std::string& value)
{
m_impl->Top()[name] = value;
return true;
}
bool JsonSerializationContext::Read(std::string_view name, std::string* value)
{
if (!m_impl->Top()[name].is_string())
{
NazaraAssert(m_impl->Top()[name].is_string(), "Value failed check: is_string()");
return false;
}
*value = m_impl->Top()[name].get<std::string>();
return true;
}
}

View File

@ -107,7 +107,7 @@ local modules = {
remove_files("src/Nazara/Core/Posix/TimeImpl.cpp")
end
end,
Packages = { "concurrentqueue", "entt", "frozen", "ordered_map", "stb", "utfcpp" },
Packages = { "concurrentqueue", "entt", "frozen", "ordered_map", "stb", "utfcpp", "nlohmann_json" },
PublicPackages = { "nazarautils" }
},
Graphics = {
@ -284,7 +284,8 @@ add_requires(
"ordered_map",
"nazarautils >=2024.01.25",
"stb",
"utfcpp"
"utfcpp",
"nlohmann_json"
)
-- Don't link with system-installed libs on CI