diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp index 8b6c1d154c..46cc0443da 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp @@ -150,7 +150,7 @@ namespace AZ { // Not using InsertTypeId here to avoid needing to create the temporary value and swap it in that call. node.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), - StoreTypeName(classData, context), context.GetJsonAllocator()); + StoreTypeName(classData, classData.m_typeId, context), context.GetJsonAllocator()); result = ResultCode(Tasks::WriteValue, Outcomes::Success); } return result.Combine(StoreClass(node, object, defaultObject, classData, context)); @@ -531,7 +531,7 @@ namespace AZ return ResolvePointerResult::ContinueProcessing; } - rapidjson::Value JsonSerializer::StoreTypeName(const SerializeContext::ClassData& classData, JsonSerializerContext& context) + rapidjson::Value JsonSerializer::StoreTypeName(const SerializeContext::ClassData& classData, const Uuid& typeId, JsonSerializerContext& context) { rapidjson::Value result; AZStd::vector ids = context.GetSerializeContext()->FindClassId(Crc32(classData.m_name)); @@ -544,7 +544,7 @@ namespace AZ // Only write the Uuid for the class if there are multiple classes sharing the same name. // In this case it wouldn't be enough to determine which class needs to be used. The // class name is still added as a comment for be friendlier for users to read. - AZStd::string fullName = classData.m_typeId.ToString(); + AZStd::string fullName = typeId.ToString(); fullName += ' '; fullName += classData.m_name; result.SetString(fullName.c_str(), aznumeric_caster(fullName.size()), context.GetJsonAllocator()); @@ -560,7 +560,7 @@ namespace AZ const SerializeContext::ClassData* data = context.GetSerializeContext()->FindClassData(typeId); if (data) { - output = JsonSerializer::StoreTypeName(*data, context); + output = JsonSerializer::StoreTypeName(*data, typeId, context); return context.Report(Tasks::WriteValue, Outcomes::Success, "Type id successfully stored to json value."); } else @@ -580,7 +580,7 @@ namespace AZ { rapidjson::Value insertedObject(rapidjson::kObjectType); insertedObject.AddMember( - rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), StoreTypeName(classData, context), + rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), StoreTypeName(classData, classData.m_typeId, context), context.GetJsonAllocator()); for (auto& element : output.GetObject()) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h index 22dd768ec5..0b72fca529 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h @@ -79,7 +79,7 @@ namespace AZ const void*& object, const void*& defaultObject, AZStd::any& defaultObjectStorage, const SerializeContext::ClassData*& elementClassData, const AZ::IRttiHelper& rtti, JsonSerializerContext& context); - static rapidjson::Value StoreTypeName(const SerializeContext::ClassData& classData, JsonSerializerContext& context); + static rapidjson::Value StoreTypeName(const SerializeContext::ClassData& classData, const Uuid& typeId, JsonSerializerContext& context); static JsonSerializationResult::ResultCode StoreTypeName(rapidjson::Value& output, const Uuid& typeId, JsonSerializerContext& context); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_TypeId.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_TypeId.cpp index 60b8f55dce..c6c08ca9ae 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_TypeId.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_TypeId.cpp @@ -10,6 +10,72 @@ #include #include #include +#include + +namespace AZ +{ + template + struct SerializeGenericTypeInfo> + { + using ThisType = JsonSerializationTests::TemplatedClass; + + class GenericTemplatedClassInfo : public GenericClassInfo + { + public: + GenericTemplatedClassInfo() + : m_classData{ SerializeContext::ClassData::Create( + "TemplatedClass", "{CA4ADF74-66E7-4D16-B4AC-F71278C60EC7}", nullptr, nullptr) } + { + } + + SerializeContext::ClassData* GetClassData() override + { + return &m_classData; + } + + size_t GetNumTemplatedArguments() override + { + return 1; + } + + const Uuid& GetSpecializedTypeId() const override + { + return m_classData.m_typeId; + } + + const Uuid& GetGenericTypeId() const override + { + return m_classData.m_typeId; + } + + const Uuid& GetTemplatedTypeId(size_t element) override + { + (void)element; + return SerializeGenericTypeInfo::GetClassTypeId(); + } + + void Reflect(SerializeContext* serializeContext) override + { + if (serializeContext) + { + serializeContext->RegisterGenericClassInfo( + GetSpecializedTypeId(), this, &AZ::AnyTypeInfoConcept>::CreateAny); + serializeContext->RegisterGenericClassInfo( + azrtti_typeid(), this, + &AZ::AnyTypeInfoConcept::CreateAny); + } + } + + SerializeContext::ClassData m_classData; + }; + + using ClassInfoType = GenericTemplatedClassInfo; + static ClassInfoType* GetGenericInfo() + { + return GetCurrentSerializeContextModule().CreateGenericClassInfo(); + } + }; +} // namespace AZ namespace JsonSerializationTests { @@ -286,4 +352,32 @@ namespace JsonSerializationTests EXPECT_EQ(Processing::Halted, result.GetProcessing()); EXPECT_EQ(Outcomes::Unknown, result.GetOutcome()); } + + TEST_F(JsonSerializationTests, StoreTypeId_TemplatedType_StoresUuidWithName) + { + using namespace AZ; + using namespace AZ::JsonSerializationResult; + + m_serializeContext->RegisterGenericType>(); + m_serializeContext->RegisterGenericType>(); + + Uuid input = azrtti_typeid>(); + ResultCode result = JsonSerialization::StoreTypeId( + *m_jsonDocument, m_jsonDocument->GetAllocator(), input, AZStd::string_view{}, *m_serializationSettings); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + + AZStd::string expected = + AZStd::string::format(R"("%s TemplatedClass")", azrtti_typeid>().ToString().c_str()); + Expect_DocStrEq(expected.c_str(), false); + + input = azrtti_typeid>(); + result = JsonSerialization::StoreTypeId( + *m_jsonDocument, m_jsonDocument->GetAllocator(), input, AZStd::string_view{}, *m_serializationSettings); + + expected = + AZStd::string::format(R"("%s TemplatedClass")", azrtti_typeid>().ToString().c_str()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + Expect_DocStrEq(expected.c_str(), false); + } } // namespace JsonSerializationTests