Add json serialization utils for objects to save/load from raw bytes
This commit is contained in:
@@ -15,10 +15,7 @@ using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace FlaxEngine.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Objects serialization tool (json format).
|
||||
/// </summary>
|
||||
public static class JsonSerializer
|
||||
partial class JsonSerializer
|
||||
{
|
||||
internal class SerializerCache
|
||||
{
|
||||
|
||||
30
Source/Engine/Serialization/JsonSerializer.h
Normal file
30
Source/Engine/Serialization/JsonSerializer.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/ISerializable.h"
|
||||
#include "Engine/Core/Types/Span.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
|
||||
/// <summary>
|
||||
/// Objects serialization tool (json format).
|
||||
/// </summary>
|
||||
API_CLASS(Static, Namespace="FlaxEngine.Json") class FLAXENGINE_API JsonSerializer
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(JsonSerializer);
|
||||
|
||||
/// <summary>
|
||||
/// Performs object Json serialization to the raw bytes.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to serialize (can be null).</param>
|
||||
/// <returns>The output data.</returns>
|
||||
API_FUNCTION() static Array<byte> SaveToBytes(ISerializable* obj);
|
||||
|
||||
/// <summary>
|
||||
/// Performs object Json deserialization from the raw bytes.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to deserialize (can be null).</param>
|
||||
/// <param name="data">The source data to read from.</param>
|
||||
/// <param name="engineBuild">The engine build number of the saved data. Used to resolve old object formats when loading deprecated data.</param>
|
||||
API_FUNCTION() static void LoadFromBytes(ISerializable* obj, const Span<byte>& data, int32 engineBuild);
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
struct CommonValue;
|
||||
struct Variant;
|
||||
struct VariantType;
|
||||
class ISerializable;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all data read streams
|
||||
@@ -204,6 +205,13 @@ public:
|
||||
ReadBytes(data->Get(), size * sizeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes object from Json by reading it as a raw data (ver+length+bytes).
|
||||
/// </summary>
|
||||
/// <remarks>Reads version number, data length and actual data bytes from the stream.</remarks>
|
||||
/// <param name="obj">The object to deserialize.</param>
|
||||
void ReadJson(ISerializable* obj);
|
||||
|
||||
public:
|
||||
|
||||
// [Stream]
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
#include "ReadStream.h"
|
||||
#include "WriteStream.h"
|
||||
#include "JsonWriters.h"
|
||||
#include "JsonSerializer.h"
|
||||
#include "MemoryReadStream.h"
|
||||
#include "Engine/Core/Types/CommonValue.h"
|
||||
#include "Engine/Core/Types/Variant.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Core/Cache.h"
|
||||
#include "Engine/Debug/DebugLog.h"
|
||||
#include "Engine/Debug/Exceptions/JsonParseException.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Scripting/ManagedSerialization.h"
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
@@ -489,6 +494,29 @@ void ReadStream::ReadVariant(Variant* data)
|
||||
}
|
||||
}
|
||||
|
||||
void ReadStream::ReadJson(ISerializable* obj)
|
||||
{
|
||||
int32 engineBuild, size;
|
||||
ReadInt32(&engineBuild);
|
||||
ReadInt32(&size);
|
||||
if (obj)
|
||||
{
|
||||
if (const auto memoryStream = dynamic_cast<MemoryReadStream*>(this))
|
||||
{
|
||||
JsonSerializer::LoadFromBytes(obj, Span<byte>((byte*)memoryStream->Read(size), size), engineBuild);
|
||||
}
|
||||
else
|
||||
{
|
||||
void* data = Allocator::Allocate(size);
|
||||
ReadBytes(data, size);
|
||||
JsonSerializer::LoadFromBytes(obj, Span<byte>((byte*)data, size), engineBuild);
|
||||
Allocator::Free(data);
|
||||
}
|
||||
}
|
||||
else
|
||||
SetPosition(GetPosition() + size);
|
||||
}
|
||||
|
||||
void WriteStream::WriteText(const StringView& text)
|
||||
{
|
||||
for (int32 i = 0; i < text.Length(); i++)
|
||||
@@ -734,3 +762,57 @@ void WriteStream::WriteVariant(const Variant& data)
|
||||
CRASH;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteStream::WriteJson(ISerializable* obj, const void* otherObj)
|
||||
{
|
||||
WriteInt32(FLAXENGINE_VERSION_BUILD);
|
||||
if (obj)
|
||||
{
|
||||
rapidjson_flax::StringBuffer buffer;
|
||||
CompactJsonWriter writer(buffer);
|
||||
writer.StartObject();
|
||||
obj->Serialize(writer, otherObj);
|
||||
writer.EndObject();
|
||||
|
||||
WriteInt32((int32)buffer.GetSize());
|
||||
WriteBytes((byte*)buffer.GetString(), (int32)buffer.GetSize());
|
||||
}
|
||||
else
|
||||
WriteInt32(0);
|
||||
}
|
||||
|
||||
Array<byte> JsonSerializer::SaveToBytes(ISerializable* obj)
|
||||
{
|
||||
Array<byte> result;
|
||||
if (obj)
|
||||
{
|
||||
rapidjson_flax::StringBuffer buffer;
|
||||
CompactJsonWriter writer(buffer);
|
||||
writer.StartObject();
|
||||
obj->Serialize(writer, nullptr);
|
||||
writer.EndObject();
|
||||
result.Set((byte*)buffer.GetString(), (int32)buffer.GetSize());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void JsonSerializer::LoadFromBytes(ISerializable* obj, const Span<byte>& data, int32 engineBuild)
|
||||
{
|
||||
if (!obj || data.Length() == 0)
|
||||
return;
|
||||
|
||||
ISerializable::SerializeDocument document;
|
||||
{
|
||||
PROFILE_CPU_NAMED("Json.Parse");
|
||||
document.Parse((const char*)data.Get(), data.Length());
|
||||
}
|
||||
if (document.HasParseError())
|
||||
{
|
||||
Log::JsonParseException(document.GetParseError(), document.GetErrorOffset());
|
||||
return;
|
||||
}
|
||||
|
||||
auto modifier = Cache::ISerializeModifier.Get();
|
||||
modifier->EngineBuild = engineBuild;
|
||||
obj->Deserialize(document, modifier.Value);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
struct CommonValue;
|
||||
struct Variant;
|
||||
struct VariantType;
|
||||
class ISerializable;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all data write streams
|
||||
@@ -240,6 +241,14 @@ public:
|
||||
WriteBytes(data.Get(), size * sizeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes object to Json and writes it as a raw data (ver+length+bytes).
|
||||
/// </summary>
|
||||
/// <remarks>Writes version number, data length and actual data bytes to the stream.</remarks>
|
||||
/// <param name="obj">The object to serialize.</param>
|
||||
/// <param name="otherObj">The instance of the object to compare with and serialize only the modified properties. If null, then serialize all properties.</param>
|
||||
void WriteJson(ISerializable* obj, const void* otherObj = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
// [Stream]
|
||||
|
||||
Reference in New Issue
Block a user