[Serialization] Add Json serializer
This commit is contained in:
132
src/Nazara/Core/JsonSerialization.cpp
Normal file
132
src/Nazara/Core/JsonSerialization.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user