Initial saving/loading of JSON serialization of sc editor assets

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
This commit is contained in:
chcurran
2021-08-17 13:47:20 -07:00
parent 5044204839
commit 0270fb7fbe
33 changed files with 418 additions and 154 deletions
@@ -213,9 +213,13 @@ namespace AZ
void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags)
{
bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance;
JsonDeserializer::UseTypeDeserializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer
? JsonDeserializer::UseTypeDeserializer::No
: JsonDeserializer::UseTypeDeserializer::Yes;
return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer
? JsonDeserializer::LoadToPointer(object, typeId, value, context)
: JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, context);
? JsonDeserializer::LoadToPointer(object, typeId, value, useCustom, context)
: JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, useCustom, context);
}
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring(
@@ -224,11 +228,15 @@ namespace AZ
{
using namespace JsonSerializationResult;
JsonSerializer::UseTypeSerializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer
? JsonSerializer::UseTypeSerializer::No
: JsonSerializer::UseTypeSerializer::Yes;
if ((flags & ContinuationFlags::ReplaceDefault) == ContinuationFlags::ReplaceDefault && !context.ShouldKeepDefaults())
{
if ((flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer)
{
return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, context);
return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, useCustom, context);
}
else
{
@@ -241,19 +249,19 @@ namespace AZ
{
return result;
}
return result.Combine(JsonSerializer::Store(output, object, nullptr, typeId, context));
return result.Combine(JsonSerializer::Store(output, object, nullptr, typeId, useCustom, context));
}
else
{
void* defaultObjectPtr = AZStd::any_cast<void>(&newDefaultObject);
return JsonSerializer::Store(output, object, defaultObjectPtr, typeId, context);
return JsonSerializer::Store(output, object, defaultObjectPtr, typeId, useCustom, context);
}
}
}
return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ?
JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, context) :
JsonSerializer::Store(output, object, defaultObject, typeId, context);
JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, useCustom, context) :
JsonSerializer::Store(output, object, defaultObject, typeId, useCustom, context);
}
JsonSerializationResult::ResultCode BaseJsonSerializer::LoadTypeId(Uuid& typeId, const rapidjson::Value& input,
@@ -162,9 +162,10 @@ namespace AZ
None = 0, //! No extra flags.
ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance.
ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one.
LoadAsNewInstance = 1 << 2 //! Treats the value as if it's a newly created instance. This may trigger serializers marked with
LoadAsNewInstance = 1 << 2, //! Treats the value as if it's a newly created instance. This may trigger serializers marked with
//! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to
//! an array.
NoTypeSerializer = 1 << 3, //! Ignore the custom/specific serializer for the TypeId
};
enum class OperationFlags
@@ -38,7 +38,8 @@ namespace AZ
}
JsonSerializationResult::ResultCode JsonDeserializer::Load(
void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context)
void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, UseTypeDeserializer custom,
JsonDeserializerContext& context)
{
using namespace AZ::JsonSerializationResult;
@@ -48,8 +49,8 @@ namespace AZ
"Target object for Json Serialization is pointing to nothing during loading.");
}
BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId);
if (serializer)
if (BaseJsonSerializer* serializer
= (custom == UseTypeDeserializer::Yes ? context.GetRegistrationContext()->GetSerializerForType(typeId) : nullptr))
{
return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context);
}
@@ -70,8 +71,9 @@ namespace AZ
// type itself has not been reflected using EnumBuilder. Treat it as an enum.
return LoadEnum(object, *classData, value, context);
}
serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId());
if (serializer)
if (BaseJsonSerializer* serializer
= context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()))
{
return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context);
}
@@ -101,7 +103,7 @@ namespace AZ
}
JsonSerializationResult::ResultCode JsonDeserializer::LoadToPointer(void* object, const Uuid& typeId,
const rapidjson::Value& value, JsonDeserializerContext& context)
const rapidjson::Value& value, UseTypeDeserializer useCustom, JsonDeserializerContext& context)
{
using namespace JsonSerializationResult;
@@ -134,7 +136,7 @@ namespace AZ
const SerializeContext::ClassData* resolvedClassData = context.GetSerializeContext()->FindClassData(resolvedTypeId);
if (resolvedClassData)
{
status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, context);
status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, useCustom, context);
*objectPtr = resolvedClassData->m_azRtti->Cast(*objectPtr, typeId);
@@ -171,11 +173,11 @@ namespace AZ
}
AZ_Assert(classElement.m_azRtti->GetTypeId() == classElement.m_typeId,
"Type id mismatch during deserialization of a json file. (%s vs %s)");
return LoadToPointer(object, classElement.m_typeId, value, context);
return LoadToPointer(object, classElement.m_typeId, value, UseTypeDeserializer::Yes, context);
}
else
{
return Load(object, classElement.m_typeId, value, false, context);
return Load(object, classElement.m_typeId, value, false, UseTypeDeserializer::Yes, context);
}
}
@@ -28,6 +28,11 @@ namespace AZ
FullyProcessed,
ContinueProcessing
};
enum class UseTypeDeserializer : bool
{
No,
Yes
};
enum class TypeIdDetermination : u8
{
ExplicitTypeId, // Type id was explicitly defined using "$type".
@@ -55,10 +60,11 @@ namespace AZ
JsonDeserializer(JsonDeserializer&& rhs) = delete;
static JsonSerializationResult::ResultCode Load(
void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context);
void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, UseTypeDeserializer useCustom,
JsonDeserializerContext& context);
static JsonSerializationResult::ResultCode LoadToPointer(void* object, const Uuid& typeId, const rapidjson::Value& value,
JsonDeserializerContext& context);
UseTypeDeserializer useCustom, JsonDeserializerContext& context);
static JsonSerializationResult::ResultCode LoadWithClassElement(void* object, const rapidjson::Value& value,
const SerializeContext::ClassElement& classElement, JsonDeserializerContext& context);
@@ -245,7 +245,7 @@ namespace AZ
{
StackedString path(StackedString::Format::JsonPointer);
JsonDeserializerContext context(settings);
result = JsonDeserializer::Load(object, objectType, root, false, context);
result = JsonDeserializer::Load(object, objectType, root, false, JsonDeserializer::UseTypeDeserializer::Yes, context);
}
return result;
}
@@ -322,7 +322,7 @@ namespace AZ
JsonSerializerContext context(settings, allocator);
StackedString path(StackedString::Format::ContextPath);
result = JsonSerializer::Store(output, object, defaultObject, objectType, context);
result = JsonSerializer::Store(output, object, defaultObject, objectType, JsonSerializer::UseTypeSerializer::Yes, context);
}
return result;
}
@@ -20,7 +20,7 @@
namespace AZ
{
JsonSerializationResult::ResultCode JsonSerializer::Store(rapidjson::Value& output, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context)
const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context)
{
using namespace JsonSerializationResult;
@@ -32,8 +32,8 @@ namespace AZ
// First check if there's a generic serializer registered for this. This makes it possible to use serializers that
// are not (directly) registered with the Serialize Context.
auto serializer = context.GetRegistrationContext()->GetSerializerForType(typeId);
if (serializer)
if (BaseJsonSerializer* serializer
= (custom == UseTypeSerializer::Yes ? context.GetRegistrationContext()->GetSerializerForType(typeId) : nullptr))
{
// Start by setting the object to be an explicit default.
output.SetObject();
@@ -57,17 +57,18 @@ namespace AZ
"No factory available to create a default object for comparison.");
}
void* defaultObjectPtr = AZStd::any_cast<void>(&defaultObjectInstance);
ResultCode conversionResult = StoreWithClassData(output, object, defaultObjectPtr, *classData, StoreTypeId::No, context);
ResultCode conversionResult = StoreWithClassData(output, object, defaultObjectPtr, *classData, StoreTypeId::No
, UseTypeSerializer::Yes, context);
return ResultCode::Combine(result, conversionResult);
}
else
{
return StoreWithClassData(output, object, defaultObject, *classData, StoreTypeId::No, context);
return StoreWithClassData(output, object, defaultObject, *classData, StoreTypeId::No, custom, context);
}
}
JsonSerializationResult::ResultCode JsonSerializer::StoreFromPointer(rapidjson::Value& output, const void* object,
const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context)
const void* defaultObject, const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context)
{
using namespace JsonSerializationResult;
@@ -85,19 +86,21 @@ namespace AZ
AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch in '%s' during serialization to a json file. (%s vs %s)",
classData->m_name, classData->m_azRtti->GetTypeId().ToString<AZStd::string>().c_str(), typeId.ToString<AZStd::string>().c_str());
return StoreWithClassDataFromPointer(output, object, defaultObject, *classData, context);
return StoreWithClassDataFromPointer(output, object, defaultObject, *classData, custom, context);
}
JsonSerializationResult::ResultCode JsonSerializer::StoreWithClassData(rapidjson::Value& node, const void* object,
const void* defaultObject, const SerializeContext::ClassData& classData, StoreTypeId storeTypeId,
JsonSerializerContext& context)
UseTypeSerializer custom, JsonSerializerContext& context)
{
using namespace JsonSerializationResult;
// Start by setting the object to be an explicit default.
node.SetObject();
auto serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId);
auto serializer = custom == UseTypeSerializer::Yes
? context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId) : nullptr;
if (serializer)
{
ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context);
@@ -153,7 +156,7 @@ namespace AZ
}
JsonSerializationResult::ResultCode JsonSerializer::StoreWithClassDataFromPointer(rapidjson::Value& output, const void* object,
const void* defaultObject, const SerializeContext::ClassData& classData, JsonSerializerContext& context)
const void* defaultObject, const SerializeContext::ClassData& classData, UseTypeSerializer custom, JsonSerializerContext& context)
{
using namespace JsonSerializationResult;
@@ -176,7 +179,7 @@ namespace AZ
}
else
{
return StoreWithClassData(output, object, defaultObject, *resolvedClassData, storeTypeId, context);
return StoreWithClassData(output, object, defaultObject, *resolvedClassData, storeTypeId, custom, context);
}
}
@@ -221,8 +224,8 @@ namespace AZ
{
rapidjson::Value value;
ResultCode result = classElement.m_flags & SerializeContext::ClassElement::FLG_POINTER ?
StoreWithClassDataFromPointer(value, object, defaultObject, *elementClassData, context):
StoreWithClassData(value, object, defaultObject, *elementClassData, StoreTypeId::No, context);
StoreWithClassDataFromPointer(value, object, defaultObject, *elementClassData, UseTypeSerializer::Yes, context):
StoreWithClassData(value, object, defaultObject, *elementClassData, StoreTypeId::No, UseTypeSerializer::Yes, context);
if (result.GetProcessing() != Processing::Halted)
{
if (parentNode.IsObject())
@@ -26,6 +26,11 @@ namespace AZ
No,
Yes
};
enum class UseTypeSerializer : bool
{
No,
Yes
};
enum class ResolvePointerResult
{
FullyProcessed,
@@ -41,16 +46,18 @@ namespace AZ
JsonSerializer(JsonSerializer&& rhs) = delete;
static JsonSerializationResult::ResultCode Store(rapidjson::Value& output, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context);
const Uuid& typeId, UseTypeSerializer useCustom, JsonSerializerContext& context);
static JsonSerializationResult::ResultCode StoreFromPointer(rapidjson::Value& output, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context);
const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context);
static JsonSerializationResult::ResultCode StoreWithClassData(rapidjson::Value& node, const void* object, const void* defaultObject,
const SerializeContext::ClassData& classData, StoreTypeId storeTypeId, JsonSerializerContext& context);
const SerializeContext::ClassData& classData, StoreTypeId storeTypeId, UseTypeSerializer custom,
JsonSerializerContext& context);
static JsonSerializationResult::ResultCode StoreWithClassDataFromPointer(rapidjson::Value& output, const void* object,
const void* defaultObject, const SerializeContext::ClassData& classData, JsonSerializerContext& context);
const void* defaultObject, const SerializeContext::ClassData& classData, UseTypeSerializer custom,
JsonSerializerContext& context);
static JsonSerializationResult::ResultCode StoreWithClassElement(rapidjson::Value& parentNode, const void* object,
const void* defaultObject, const SerializeContext::ClassElement& classElement, JsonSerializerContext& context);
@@ -333,7 +333,7 @@ namespace AZ
// validate class name
auto classData = loadSettings.m_serializeContext->FindClassData(classId);
if (azstricmp(classData->m_name, className) != 0)
if (!classData || azstricmp(classData->m_name, className) != 0)
{
return AZ::Failure(AZStd::string::format("Try to load class %s from class %s data", classData->m_name, className));
}