From f00fa26e1246eb2ac7e3ebcb7dec8b3657f4600c Mon Sep 17 00:00:00 2001 From: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> Date: Tue, 15 Jun 2021 13:44:32 -0700 Subject: [PATCH] Separated initializing new and all objects in the Json Serialization Introduced OperationFlags::InitializeNewInstance to the Json Serialization which allows custom json serializers to indicate that they need to set defaults only to new instances. Objects created to fill in a pointer are considered new objects and serializer can use the new ContinuationFlags::LoadAsNewInstance to also inform that the load is happening on a new object. Serializer that use the InitializeNewInstance flag know that a new object is begin initialized if they're called with an explicit default object. --- .../AzCore/AzCore/Math/ColorSerializer.cpp | 2 +- .../AzCore/Math/MathMatrixSerializer.cpp | 2 +- .../AzCore/Math/MathVectorSerializer.cpp | 2 +- .../AzCore/Math/TransformSerializer.cpp | 2 +- .../AzCore/AzCore/Math/UuidSerializer.cpp | 2 +- .../Serialization/Json/BaseJsonSerializer.cpp | 3 ++- .../Serialization/Json/BaseJsonSerializer.h | 15 +++++++++----- .../Serialization/Json/BoolSerializer.cpp | 2 +- .../Serialization/Json/DoubleSerializer.cpp | 4 ++-- .../Serialization/Json/IntSerializer.cpp | 2 +- .../Serialization/Json/JsonDeserializer.cpp | 20 +++++++++++-------- .../Serialization/Json/JsonDeserializer.h | 5 +++-- .../Serialization/Json/JsonSerialization.cpp | 2 +- 13 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp index ffdd73ffd8..0d45a3fb6c 100644 --- a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp @@ -103,7 +103,7 @@ namespace AZ auto JsonColorSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } JsonSerializationResult::Result JsonColorSerializer::LoadObject(Color& output, const rapidjson::Value& inputValue, diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp index 3d6a378b13..7f412f68e6 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp @@ -393,7 +393,7 @@ namespace AZ auto BaseJsonMatrixSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp index 0c0bc04338..7225f1713c 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp @@ -206,7 +206,7 @@ namespace AZ auto BaseJsonVectorSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp index 49ba082618..b3c9ea3b7c 100644 --- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp @@ -148,7 +148,7 @@ namespace AZ auto JsonTransformSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp index 2c751e8a1c..458744d5b2 100644 --- a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp @@ -35,7 +35,7 @@ namespace AZ auto JsonUuidSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } JsonSerializationResult::Result JsonUuidSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp index 9a426a1e59..666fa0f96a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp @@ -216,9 +216,10 @@ namespace AZ JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading( void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags) { + bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance; return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ? JsonDeserializer::LoadToPointer(object, typeId, value, context) - : JsonDeserializer::Load(object, typeId, value, context); + : JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, context); } JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring( diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h index 06c5eda6de..99b63bf4de 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h @@ -163,15 +163,20 @@ namespace AZ enum class ContinuationFlags { - 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. + 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 + //! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to + //! an array. }; enum class OperationFlags { - None = 0, //! No flags that control how the custom json serializer is used. - ManualDefault = 1 << 0 //! Even if an (explicit) default is found the custom json serializer will still be called. + None = 0, //! No flags that control how the custom json serializer is used. + ManualDefault = 1 << 0, //! Even if an (explicit) default is found the custom json serializer will still be called. + InitializeNewInstance = 1 << 1 //! If set, the custom json serializer will be called with an explicit default if a new + //! instance of its target type is created. }; virtual ~BaseJsonSerializer() = default; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp index 4d0a29df71..defe470bcf 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp @@ -154,6 +154,6 @@ namespace AZ auto JsonBoolSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp index 647ff67eb6..14f2eaae6f 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp @@ -166,7 +166,7 @@ namespace AZ auto JsonDoubleSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } JsonSerializationResult::Result JsonFloatSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, @@ -191,6 +191,6 @@ namespace AZ auto JsonFloatSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp index 28da852da3..ebc99fd8c4 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp @@ -135,7 +135,7 @@ namespace AZ auto BaseJsonIntegerSerializer::GetOperationsFlags() const -> OperationFlags { - return OperationFlags::ManualDefault; + return OperationFlags::InitializeNewInstance; } JsonSerializationResult::Result JsonCharSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index 9c4641741e..d948966b4b 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -24,20 +24,24 @@ namespace AZ { JsonSerializationResult::ResultCode JsonDeserializer::DeserializerDefaultCheck(BaseJsonSerializer* serializer, void* object, - const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context) + const Uuid& typeId,const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context) { using namespace AZ::JsonSerializationResult; bool isExplicitDefault = IsExplicitDefault(value); bool manuallyDefaults = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::ManualDefault) == BaseJsonSerializer::OperationFlags::ManualDefault; - return !isExplicitDefault || (isExplicitDefault && manuallyDefaults) + bool initializeNewInstance = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::InitializeNewInstance) == + BaseJsonSerializer::OperationFlags::InitializeNewInstance; + + return + !isExplicitDefault || (isExplicitDefault && manuallyDefaults) || (isExplicitDefault && isNewInstance && initializeNewInstance) ? serializer->Load(object, typeId, value, context) : context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default."); } - JsonSerializationResult::ResultCode JsonDeserializer::Load(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context) + JsonSerializationResult::ResultCode JsonDeserializer::Load( + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context) { using namespace AZ::JsonSerializationResult; @@ -50,7 +54,7 @@ namespace AZ BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId); if (serializer) { - return DeserializerDefaultCheck(serializer, object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId); @@ -72,7 +76,7 @@ namespace AZ serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()); if (serializer) { - return DeserializerDefaultCheck(serializer, object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } } @@ -133,7 +137,7 @@ namespace AZ const SerializeContext::ClassData* resolvedClassData = context.GetSerializeContext()->FindClassData(resolvedTypeId); if (resolvedClassData) { - status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, context); + status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, context); *objectPtr = resolvedClassData->m_azRtti->Cast(*objectPtr, typeId); @@ -174,7 +178,7 @@ namespace AZ } else { - return Load(object, classElement.m_typeId, value, context); + return Load(object, classElement.m_typeId, value, false, context); } } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h index 5954082ee0..1d16b49e39 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h @@ -58,8 +58,8 @@ namespace AZ JsonDeserializer(const JsonDeserializer& rhs) = delete; JsonDeserializer(JsonDeserializer&& rhs) = delete; - static JsonSerializationResult::ResultCode Load(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context); + static JsonSerializationResult::ResultCode Load( + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context); static JsonSerializationResult::ResultCode LoadToPointer(void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context); @@ -120,6 +120,7 @@ namespace AZ void* object, const Uuid& typeId, const rapidjson::Value& value, + bool isNewInstance, JsonDeserializerContext& context); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp index 0629f1c32e..6fabf51237 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp @@ -249,7 +249,7 @@ namespace AZ { StackedString path(StackedString::Format::JsonPointer); JsonDeserializerContext context(settings); - result = JsonDeserializer::Load(object, objectType, root, context); + result = JsonDeserializer::Load(object, objectType, root, false, context); } return result; }