diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp index 13a25e5aa6..d5a1730364 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp @@ -74,7 +74,7 @@ namespace AZ "Unable to retrieve the correct container information for AZStd::array instance."); } - Flags flags = Flags::None; + ContinuationFlags flags = ContinuationFlags::None; Uuid elementTypeId = Uuid::CreateNull(); auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement) { @@ -82,7 +82,7 @@ namespace AZ elementTypeId = genericClassElement->m_typeId; if (genericClassElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - flags = Flags::ResolvePointer; + flags = ContinuationFlags::ResolvePointer; } return false; }; @@ -161,7 +161,7 @@ namespace AZ "Not enough entries in JSON array to load an AZStd::array from."); } - Flags flags = Flags::None; + ContinuationFlags flags = ContinuationFlags::None; Uuid elementTypeId = Uuid::CreateNull(); auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement) { @@ -169,7 +169,7 @@ namespace AZ elementTypeId = genericClassElement->m_typeId; if (genericClassElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - flags = Flags::ResolvePointer; + flags = ContinuationFlags::ResolvePointer; } return false; }; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp index 6c67fd284a..9a426a1e59 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp @@ -208,22 +208,28 @@ namespace AZ // BaseJsonSerializer // - JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context, Flags flags) + BaseJsonSerializer::OperationFlags BaseJsonSerializer::GetOperationsFlags() const { - return flags & Flags::ResolvePointer ? - JsonDeserializer::LoadToPointer(object, typeId, value, context) : - JsonDeserializer::Load(object, typeId, value, context); + return OperationFlags::None; } - JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring(rapidjson::Value& output, const void* object, - const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, Flags flags) + JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading( + void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags) + { + return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer + ? JsonDeserializer::LoadToPointer(object, typeId, value, context) + : JsonDeserializer::Load(object, typeId, value, context); + } + + JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring( + rapidjson::Value& output, const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, + ContinuationFlags flags) { using namespace JsonSerializationResult; - if (flags & Flags::ReplaceDefault && !context.ShouldKeepDefaults()) + if ((flags & ContinuationFlags::ReplaceDefault) == ContinuationFlags::ReplaceDefault && !context.ShouldKeepDefaults()) { - if (flags & Flags::ResolvePointer) + if ((flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer) { return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, context); } @@ -248,7 +254,7 @@ namespace AZ } } - return flags & Flags::ResolvePointer ? + return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ? JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, context) : JsonSerializer::Store(output, object, defaultObject, typeId, context); } @@ -265,8 +271,9 @@ namespace AZ return JsonSerializer::StoreTypeName(output, typeId, context); } - JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoadingFromJsonObjectField(void* object, const Uuid& typeId, const rapidjson::Value& value, - rapidjson::Value::StringRefType memberName, JsonDeserializerContext& context, Flags flags) + JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoadingFromJsonObjectField( + void* object, const Uuid& typeId, const rapidjson::Value& value, rapidjson::Value::StringRefType memberName, + JsonDeserializerContext& context, ContinuationFlags flags) { using namespace JsonSerializationResult; @@ -291,7 +298,7 @@ namespace AZ JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoringToJsonObjectField(rapidjson::Value& output, rapidjson::Value::StringRefType newMemberName, const void* object, const void* defaultObject, - const Uuid& typeId, JsonSerializerContext& context, Flags flags) + const Uuid& typeId, JsonSerializerContext& context, ContinuationFlags flags) { using namespace JsonSerializationResult; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h index f6ced44583..06c5eda6de 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h @@ -161,13 +161,19 @@ namespace AZ public: AZ_RTTI(BaseJsonSerializer, "{7291FFDC-D339-40B5-BB26-EA067A327B21}"); - enum Flags + enum class ContinuationFlags { - None = 0, //! No extra flags. + 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. }; + 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. + }; + virtual ~BaseJsonSerializer() = default; //! Transforms the data from the rapidjson Value to outputValue, if the conversion is possible and supported. @@ -180,6 +186,9 @@ namespace AZ virtual JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) = 0; + //! Returns the operation flags which tells the Json Serialization how this custom json serializer can be used. + virtual OperationFlags GetOperationsFlags() const; + protected: //! Continues loading of a (sub)value. Use this function to load member variables for instance. This is more optimal than //! directly calling the json serialization. @@ -187,8 +196,9 @@ namespace AZ //! @param typeId Type id of the object passed in. //! @param value The value in the JSON document where the deserializer will start reading data from. //! @param context The context used during deserialization. Use the value passed in from Load. - JsonSerializationResult::ResultCode ContinueLoading(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context, Flags flags = Flags::None); + JsonSerializationResult::ResultCode ContinueLoading( + void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, + ContinuationFlags flags = ContinuationFlags::None); //! Continues storing of a (sub)value. Use this function to store member variables for instance. This is more optimal than //! directly calling the json serialization. @@ -200,8 +210,9 @@ namespace AZ //! the settings. //! @param typeId The type id of the object and default object. //! @param context The context used during serialization. Use the value passed in from Store. - JsonSerializationResult::ResultCode ContinueStoring(rapidjson::Value& output, const void* object, const void* defaultObject, - const Uuid& typeId, JsonSerializerContext& context, Flags flags = Flags::None); + JsonSerializationResult::ResultCode ContinueStoring( + rapidjson::Value& output, const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, + ContinuationFlags flags = ContinuationFlags::None); //! Retrieves the type id from a json object or json string. //! @param typeId The retrieved type id. @@ -222,12 +233,14 @@ namespace AZ const Uuid& typeId, JsonSerializerContext& context); //! Helper function similar to ContinueLoading, but loads the data as a member of 'value' rather than 'value' itself, if it exists. - JsonSerializationResult::ResultCode ContinueLoadingFromJsonObjectField(void* object, const Uuid& typeId, const rapidjson::Value& value, - rapidjson::Value::StringRefType memberName, JsonDeserializerContext& context, Flags flags = Flags::None); + JsonSerializationResult::ResultCode ContinueLoadingFromJsonObjectField( + void* object, const Uuid& typeId, const rapidjson::Value& value, rapidjson::Value::StringRefType memberName, + JsonDeserializerContext& context, ContinuationFlags flags = ContinuationFlags::None); //! Helper function similar to ContinueStoring, but stores the data as a member of 'output' rather than overwriting 'output'. - JsonSerializationResult::ResultCode ContinueStoringToJsonObjectField(rapidjson::Value& output, rapidjson::Value::StringRefType newMemberName, - const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, Flags flags = Flags::None); + JsonSerializationResult::ResultCode ContinueStoringToJsonObjectField( + rapidjson::Value& output, rapidjson::Value::StringRefType newMemberName, const void* object, const void* defaultObject, + const Uuid& typeId, JsonSerializerContext& context, ContinuationFlags flags = ContinuationFlags::None); //! Checks if a value is an explicit default. This useful for containers where not storing anything as a default would mean //! a slot wouldn't be used so something has to be added to represent the fully default target. @@ -238,6 +251,7 @@ namespace AZ rapidjson::Value GetExplicitDefault(); }; - AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::Flags) + AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::ContinuationFlags) + AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::OperationFlags) } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp index c15cb9ef54..400a3b7949 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp @@ -75,9 +75,10 @@ namespace AZ auto elementCallback = [this, &array, &retVal, &index, &context] (void* elementPtr, const Uuid& elementId, const SerializeContext::ClassData*, const SerializeContext::ClassElement* classElement) { - Flags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? - Flags::ResolvePointer : Flags::None; - flags |= Flags::ReplaceDefault; + ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER + ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None; + flags |= ContinuationFlags::ReplaceDefault; ScopedContextPath subPath(context, index); index++; @@ -161,8 +162,9 @@ namespace AZ container->EnumTypes(typeEnumCallback); AZ_Assert(classElement, "No class element found for the type in the basic container."); - Flags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? - Flags::ResolvePointer : Flags::None; + ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER + ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None; const size_t capacity = container->IsFixedCapacity() ? container->Capacity(outputValue) : std::numeric_limits::max(); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index 8d0da9e54a..93d12acba3 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -22,6 +22,19 @@ namespace AZ { + JsonSerializationResult::ResultCode JsonDeserializer::DeserializerDefaultCheck(BaseJsonSerializer* serializer, void* object, + const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context) + { + using namespace AZ::JsonSerializationResult; + + bool isExplicitDefault = IsExplicitDefault(value); + bool manuallyDefaults = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::ManualDefault) == + BaseJsonSerializer::OperationFlags::ManualDefault; + return !isExplicitDefault || (isExplicitDefault && manuallyDefaults) + ? 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) { @@ -33,17 +46,12 @@ namespace AZ "Target object for Json Serialization is pointing to nothing during loading."); } - if (IsExplicitDefault(value)) - { - return context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default."); - } - BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId); if (serializer) { - return serializer->Load(object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, context); } - + const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId); if (!classData) { @@ -56,9 +64,14 @@ namespace AZ serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()); if (serializer) { - return serializer->Load(object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, context); } } + + if (IsExplicitDefault(value)) + { + return context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default."); + } if (classData->m_azRtti && (classData->m_azRtti->GetTypeTraits() & AZ::TypeTraits::is_enum) == AZ::TypeTraits::is_enum) { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h index 89e527b9ae..5954082ee0 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h @@ -113,5 +113,13 @@ namespace AZ //! Checks if a value is an explicit default. This means the value is an object with no members. static bool IsExplicitDefault(const rapidjson::Value& value); + + private: + static JsonSerializationResult::ResultCode DeserializerDefaultCheck( + BaseJsonSerializer* serializer, + void* object, + const Uuid& typeId, + const rapidjson::Value& value, + JsonDeserializerContext& context); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp index fa244d3dae..437a648e1e 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp @@ -215,10 +215,10 @@ namespace AZ // Load key void* keyAddress = pairContainer->GetElementByIndex(address, pairElement, 0); AZ_Assert(keyAddress, "Element reserved for associative container, but unable to retrieve address of the key."); - Flags keyLoadFlags = Flags::None; + ContinuationFlags keyLoadFlags = ContinuationFlags::None; if (keyElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - keyLoadFlags = Flags::ResolvePointer; + keyLoadFlags = ContinuationFlags::ResolvePointer; *reinterpret_cast(keyAddress) = nullptr; } JSR::ResultCode keyResult = ContinueLoading(keyAddress, keyElement->m_typeId, key, context, keyLoadFlags); @@ -231,10 +231,10 @@ namespace AZ // Load value void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1); AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value."); - Flags valueLoadFlags = Flags::None; + ContinuationFlags valueLoadFlags = ContinuationFlags::None; if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - valueLoadFlags = Flags::ResolvePointer; + valueLoadFlags = ContinuationFlags::ResolvePointer; *reinterpret_cast(valueAddress) = nullptr; } JSR::ResultCode valueResult = ContinueLoading(valueAddress, valueElement->m_typeId, value, context, valueLoadFlags); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp index 9e707f8644..0ab32ac08d 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp @@ -82,7 +82,7 @@ namespace AZ { // If the target type is the same as the type already stored in the smart pointer than no new // instance is created and the existing instance will be updated with the data in the json document. - result = ContinueLoading(instance, elementClassId, inputValue, context, Flags::ResolvePointer); + result = ContinueLoading(instance, elementClassId, inputValue, context, ContinuationFlags::ResolvePointer); return false; } } @@ -93,7 +93,7 @@ namespace AZ // the wrong address. In these cases explicitly reset the smart pointer. This will erase the existing // data but that's fine as it's not being used. void* element = nullptr; - result = ContinueLoading(&element, elementClassId, inputValue, context, Flags::ResolvePointer); + result = ContinueLoading(&element, elementClassId, inputValue, context, ContinuationFlags::ResolvePointer); if (result.GetProcessing() != JSR::Processing::Halted && result.GetProcessing() != JSR::Processing::Altered) { void* elementPtr = container->ReserveElement(instance, nullptr); @@ -155,8 +155,14 @@ namespace AZ container->EnumElements(const_cast(defaultValue), defaultInputCallback); } - JSR::ResultCode result = ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, Flags::ResolvePointer); + JSR::ResultCode result = + ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, ContinuationFlags::ResolvePointer); return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "Successfully processed smart pointer." : "A problem occurred while processing a smart pointer."); } + + BaseJsonSerializer::OperationFlags JsonSmartPointerSerializer::GetOperationsFlags() const + { + return OperationFlags::ManualDefault; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.h index 8c550cb824..9a0cf61be9 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.h @@ -28,5 +28,7 @@ namespace AZ JsonDeserializerContext& context) override; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + + OperationFlags GetOperationsFlags() const override; }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp index 9ea22592bc..5b43cec817 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp @@ -99,8 +99,9 @@ namespace AZ ScopedContextPath subPath(context, i); - Flags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? - Flags::ResolvePointer : Flags::None; + ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER + ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None; JSR::ResultCode result = ContinueStoring(elementValues[i], elementAddress, defaultElementAddress, classElements[i]->m_typeId, context, flags); @@ -179,8 +180,9 @@ namespace AZ void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i); AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i); - Flags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? - Flags::ResolvePointer : Flags::None; + ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER + ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None; while (arrayIndex < inputValue.Size()) { diff --git a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp index a494207850..e44f77b119 100644 --- a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp @@ -104,6 +104,11 @@ namespace JsonSerializationTests AZ::AllocatorInstance::Destroy(); } + void Reflect(AZStd::unique_ptr& context) override + { + context->RegisterGenericType(); + } + AZStd::shared_ptr CreateSerializer() override { return AZStd::make_shared(); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp index 08de21b54f..47e05997fc 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp @@ -119,7 +119,8 @@ namespace JsonSerializationTests int value = 0; int* ptrValue = &value; - ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + ResultCode result = + ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); ASSERT_NE(nullptr, ptrValue); @@ -134,7 +135,8 @@ namespace JsonSerializationTests json.Set(42); int* ptrValue = nullptr; - ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + ResultCode result = + ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); ASSERT_NE(nullptr, ptrValue); @@ -150,7 +152,8 @@ namespace JsonSerializationTests rapidjson::Value json(rapidjson::kObjectType); int* ptrValue = nullptr; - ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + ResultCode result = + ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); ASSERT_NE(nullptr, ptrValue); @@ -165,7 +168,8 @@ namespace JsonSerializationTests rapidjson::Value json(rapidjson::kNullType); int* ptrValue = reinterpret_cast(azmalloc(sizeof(int), alignof(int), AZ::SystemAllocator)); - ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + ResultCode result = + ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); ASSERT_EQ(nullptr, ptrValue); @@ -194,8 +198,8 @@ namespace JsonSerializationTests int value = 42; int* ptrValue = &value; - ResultCode result = ContinueStoring(*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, - Flags::ResolvePointer); + ResultCode result = ContinueStoring( + *m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("42"); @@ -210,8 +214,9 @@ namespace JsonSerializationTests int value2 = 42; int* defaultPtrValue = &value2; - ResultCode result = - ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + ResultCode result = ContinueStoring( + *m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, + ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("{}"); @@ -224,7 +229,7 @@ namespace JsonSerializationTests int* ptrValue = nullptr; ResultCode result = ContinueStoring( - *m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + *m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("null"); @@ -238,8 +243,9 @@ namespace JsonSerializationTests int value2 = 42; int* defaultPtrValue = &value2; - ResultCode result = - ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + ResultCode result = ContinueStoring( + *m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, + ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("null"); @@ -252,8 +258,9 @@ namespace JsonSerializationTests int* ptrValue = nullptr; int* defaultPtrValue = nullptr; - ResultCode result = - ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + ResultCode result = ContinueStoring( + *m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, + ContinuationFlags::ResolvePointer); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("null"); @@ -265,8 +272,8 @@ namespace JsonSerializationTests int value = 42; - ResultCode result = ContinueStoring(*m_jsonDocument, &value, nullptr, azrtti_typeid(), *m_jsonSerializationContext, - Flags::ReplaceDefault); + ResultCode result = ContinueStoring( + *m_jsonDocument, &value, nullptr, azrtti_typeid(), *m_jsonSerializationContext, ContinuationFlags::ReplaceDefault); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("42"); @@ -280,7 +287,7 @@ namespace JsonSerializationTests int* ptrValue = &value; ResultCode result = ContinueStoring(*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, - Flags::ResolvePointer | Flags::ReplaceDefault); + ContinuationFlags::ResolvePointer | ContinuationFlags::ReplaceDefault); EXPECT_EQ(Processing::Completed, result.GetProcessing()); Expect_DocStrEq("42"); @@ -293,8 +300,8 @@ namespace JsonSerializationTests int value = 42; AZ::Uuid unknownType("{09AE3CEC-EBFC-41EC-A7F6-949721521716}"); - ResultCode result = ContinueStoring(*m_jsonDocument, &value, nullptr, unknownType, *m_jsonSerializationContext, - Flags::ReplaceDefault); + ResultCode result = + ContinueStoring(*m_jsonDocument, &value, nullptr, unknownType, *m_jsonSerializationContext, ContinuationFlags::ReplaceDefault); EXPECT_EQ(Processing::Halted, result.GetProcessing()); } diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h index 4f0825ff1b..c0f470378c 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h +++ b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h @@ -90,9 +90,14 @@ namespace JsonSerializationTests virtual ~JsonSerializerConformityTestDescriptor() = default; virtual AZStd::shared_ptr CreateSerializer() = 0; - + //! Create an instance of the target type with all values set to default. virtual AZStd::shared_ptr CreateDefaultInstance() = 0; + //! Create an instance of the target type that constructed with default constructor. + //! This will be the same instance that Json Serialization creates for dynamic types. Typically it's the same + //! as from CreateDefaultInstance(), except of types, such as pointers, that need to do minimal (de)serialization + //! to initialize an object. + virtual AZStd::shared_ptr CreateDefaultConstructedInstance() { return CreateDefaultInstance(); } //! Create an instance of the target type with some values set and some kept on defaults. //! If the target type doesn't support partial specialization this can be ignored and //! tests for partial support will be skipped. @@ -316,10 +321,10 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto original = this->m_description.CreateDefaultInstance(); - ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*original), + ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); if (this->m_features.m_mandatoryFields.empty()) @@ -339,6 +344,42 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeEmptyObjectThroughMainLoad_SucceedsAndObjectMatchesDefaults) + { + using namespace AZ::JsonSerializationResult; + + if (this->m_features.SupportsJsonType(rapidjson::kObjectType)) + { + this->m_jsonDocument->Parse("{}"); + ASSERT_FALSE(this->m_jsonDocument->HasParseError()); + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); + auto original = this->m_description.CreateDefaultInstance(); + + AZ::JsonDeserializerSettings settings; + settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext(); + settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext(); + ResultCode result = AZ::JsonSerialization::Load( + instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, settings); + + if (this->m_features.m_mandatoryFields.empty()) + { + EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + } + else + { + EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome()); + bool validProcessing = + result.GetProcessing() == Processing::Altered || + result.GetProcessing() == Processing::PartialAlter; + EXPECT_TRUE(validProcessing); + } + EXPECT_TRUE(this->m_description.AreEqual(*original, *instance)); + } + } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults) { using namespace AZ::JsonSerializationResult; @@ -349,7 +390,7 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto original = this->m_description.CreateDefaultInstance(); this->m_deserializationSettings->m_clearContainers = false; @@ -384,7 +425,7 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto original = this->m_description.CreateDefaultInstance(); this->m_deserializationSettings->m_clearContainers = true; @@ -488,7 +529,7 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto compare = this->m_description.CreateFullySetInstance(); ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance), @@ -499,6 +540,28 @@ namespace JsonSerializationTests EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare)); } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance) + { + using namespace AZ::JsonSerializationResult; + + AZStd::string_view json = this->m_description.GetJsonFor_Load_DeserializeFullySetInstance(); + this->m_jsonDocument->Parse(json.data()); + ASSERT_FALSE(this->m_jsonDocument->HasParseError()); + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); + auto compare = this->m_description.CreateFullySetInstance(); + + AZ::JsonDeserializerSettings settings; + settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext(); + settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext(); + ResultCode result = AZ::JsonSerialization::Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, settings); + + EXPECT_EQ(Outcomes::Success, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare)); + } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported) { using namespace AZ::JsonSerializationResult; @@ -518,7 +581,7 @@ namespace JsonSerializationTests ASSERT_NE(this->m_jsonDocument->MemberEnd(), memberToErase); this->m_jsonDocument->RemoveMember(memberToErase); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); @@ -546,7 +609,7 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto compare = this->m_description.CreatePartialDefaultInstance(); ASSERT_NE(nullptr, compare); @@ -567,7 +630,7 @@ namespace JsonSerializationTests ASSERT_FALSE(this->m_jsonDocument->HasParseError()); auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); AZ::ScopedContextReporter reporter(*this->m_jsonDeserializationContext, [](AZStd::string_view message, ResultCode result, AZStd::string_view path) -> ResultCode @@ -604,7 +667,7 @@ namespace JsonSerializationTests } auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); auto compare = this->m_description.CreateFullySetInstance(); ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance), @@ -635,7 +698,7 @@ namespace JsonSerializationTests } auto serializer = this->m_description.CreateSerializer(); - auto instance = this->m_description.CreateDefaultInstance(); + auto instance = this->m_description.CreateDefaultConstructedInstance(); ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); @@ -693,6 +756,36 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeDefaultInstanceThroughMainStore_EmptyJsonReturned) + { + using namespace AZ::JsonSerializationResult; + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreateDefaultInstance(); + rapidjson::Value convertedValue = this->CreateExplicitDefault(); + + AZ::JsonSerializerSettings settings; + settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext(); + settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext(); + ResultCode result = AZ::JsonSerialization::Store( + convertedValue, this->m_jsonDocument->GetAllocator(), instance.get(), instance.get(), azrtti_typeid(*instance), settings); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + if (convertedValue.IsObject() && !this->m_features.m_mandatoryFields.empty()) + { + ASSERT_EQ(convertedValue.MemberCount(), this->m_features.m_mandatoryFields.size()); + for (const AZStd::string& mandatoryField : this->m_features.m_mandatoryFields) + { + EXPECT_NE(convertedValue.MemberEnd(), convertedValue.FindMember(mandatoryField.c_str())); + } + } + else + { + EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + this->Expect_ExplicitDefault(convertedValue); + } + } + TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeWithDefaultsKept_FullyWrittenJson) { using namespace AZ::JsonSerializationResult; @@ -924,6 +1017,20 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared) + { + if (this->m_features.SupportsJsonType(rapidjson::kObjectType)) + { + if (!this->m_features.m_mandatoryFields.empty()) + { + auto serializer = this->m_description.CreateSerializer(); + bool manuallyHandlesDefaults = (serializer->GetOperationsFlags() & AZ::BaseJsonSerializer::OperationFlags::ManualDefault) == + AZ::BaseJsonSerializer::OperationFlags::ManualDefault; + EXPECT_TRUE(manuallyHandlesDefaults); + } + } + } + REGISTER_TYPED_TEST_CASE_P(JsonSerializerConformityTests, Registration_SerializerIsRegisteredWithContext_SerializerFound, @@ -934,14 +1041,16 @@ namespace JsonSerializationTests Load_InvalidTypeOfArrayType_ReturnsUnsupported, Load_InvalidTypeOfStringType_ReturnsUnsupported, Load_InvalidTypeOfNumberType_ReturnsUnsupported, - + Load_DeserializeUnreflectedType_ReturnsUnsupported, Load_DeserializeEmptyObject_SucceedsAndObjectMatchesDefaults, + Load_DeserializeEmptyObjectThroughMainLoad_SucceedsAndObjectMatchesDefaults, Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults, Load_DeserializeEmptyArrayWithClearEnabled_SucceedsAndObjectMatchesDefaults, Load_DeserializeEmptyArrayWithClearedTarget_SucceedsAndObjectMatchesDefaults, Load_InterruptClearingTarget_ContainerIsNotCleared, Load_DeserializeFullySetInstance_SucceedsAndObjectMatchesFullySetInstance, + Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance, Load_DeserializePartialInstance_SucceedsAndObjectMatchesParialInstance, Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported, Load_InsertAdditionalData_SucceedsAndObjectMatchesFullySetInstance, @@ -950,6 +1059,7 @@ namespace JsonSerializationTests Store_SerializeUnreflectedType_ReturnsUnsupported, Store_SerializeDefaultInstance_EmptyJsonReturned, + Store_SerializeDefaultInstanceThroughMainStore_EmptyJsonReturned, Store_SerializeWithDefaultsKept_FullyWrittenJson, Store_SerializeFullySetInstance_StoredSuccessfullyAndJsonMatches, Store_SerializeWithoutDefault_StoredSuccessfullyAndJsonMatches, @@ -957,10 +1067,12 @@ namespace JsonSerializationTests Store_SerializePartialInstance_StoredSuccessfullyAndJsonMatches, Store_SerializeEmptyArray_StoredSuccessfullyAndJsonMatches, Store_HaltedThroughCallback_StoreFailsAndHaltReported, - + StoreLoad_RoundTripWithPartialDefault_IdenticalInstances, StoreLoad_RoundTripWithFullSet_IdenticalInstances, - StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances); + StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances, + + GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared); } // namespace JsonSerializationTests namespace AZ diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp index 2fc131aae2..75391d81d4 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp @@ -32,6 +32,11 @@ namespace JsonSerializationTests return AZStd::make_shared(); } + AZStd::shared_ptr CreateDefaultConstructedInstance() override + { + return AZStd::make_shared(); + } + void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -228,13 +233,19 @@ namespace JsonSerializationTests public: using SmartPointer = typename SmartPointerSimpleDerivedClassTestDescription::SmartPointer; - AZStd::shared_ptr CreateDefaultInstance() override + // This test is specific for derived classes being used as a default value. + AZStd::shared_ptr CreateDefaultConstructedInstance() override { auto result = AZStd::make_shared(); *result = SmartPointer(aznew SimpleInheritence()); return result; } + AZStd::shared_ptr CreateDefaultInstance() override + { + return CreateDefaultConstructedInstance(); + } + AZStd::string_view GetJsonForPartialDefaultInstance() override { return R"( @@ -386,13 +397,19 @@ namespace JsonSerializationTests public: using SmartPointer = typename SmartPointerComplexDerivedClassTestDescription::SmartPointer; - AZStd::shared_ptr CreateDefaultInstance() override + // This test is specific for derived classes being used as a default value. + AZStd::shared_ptr CreateDefaultConstructedInstance() override { auto result = AZStd::make_shared(); *result = SmartPointer(aznew MultipleInheritence()); return result; } + AZStd::shared_ptr CreateDefaultInstance() override + { + return CreateDefaultConstructedInstance(); + } + AZStd::string_view GetJsonForPartialDefaultInstance() override { return R"( diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp index 52eae22fee..a535f5f65d 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp @@ -48,6 +48,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("Radius", &SphereShapeConfiguration::m_radius) @@ -76,6 +79,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("Configuration", &BoxShapeConfiguration::m_dimensions) @@ -104,6 +110,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("Height", &CapsuleShapeConfiguration::m_height) @@ -153,6 +162,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset) @@ -185,6 +197,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("Scale", &NativeShapeConfiguration::m_nativeShapeScale) @@ -208,6 +223,9 @@ namespace Physics { if (auto serializeContext = azrtti_cast(context)) { + serializeContext + ->RegisterGenericType>(); + serializeContext->Class() ->Version(1) ->Field("CookedData", &CookedMeshShapeConfiguration::m_cookedData) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h index 59f129b52a..a10e773891 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h @@ -33,6 +33,8 @@ namespace AZ JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + private: + BaseJsonSerializer::OperationFlags GetOperationsFlags() const override; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp index a31d97c913..7ac8240faa 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp @@ -127,5 +127,10 @@ namespace AZ return context.Report(result, "Successfully processed MaterialFunctorSourceData."); } + + BaseJsonSerializer::OperationFlags JsonMaterialFunctorSourceDataSerializer::GetOperationsFlags() const + { + return OperationFlags::ManualDefault; + } } // namespace RPI } // namespace AZ