Files
UnrealEngine/Engine/Source/Runtime/Json/Public/Serialization/JsonSerializerMacros.h
2025-05-18 13:04:45 +08:00

413 lines
13 KiB
C

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Policies/PrettyJsonPrintPolicy.h"
#include "Policies/CondensedJsonPrintPolicy.h"
#include "Serialization/JsonDataBag.h"
#include "Serialization/JsonTypes.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonSerializer.h"
#include "Serialization/JsonSerializable.h"
#include "Serialization/JsonSerializerBase.h"
#include "Serialization/JsonSerializerReader.h"
#include "Serialization/JsonSerializerWriter.h"
#include "JsonGlobals.h"
/**
* Macros used to generate a serialization function for a class derived from FJsonSerializable
*/
#define BEGIN_JSON_SERIALIZER \
virtual void Serialize(FJsonSerializerBase& Serializer, bool bFlatObject) override \
{ \
if (!bFlatObject) { Serializer.StartObject(); }
#define END_JSON_SERIALIZER \
if (!bFlatObject) { Serializer.EndObject(); } \
}
#define JSON_SERIALIZE(JsonName, JsonValue) \
Serializer.Serialize(TEXTVIEW(JsonName), JsonValue)
#define JSON_SERIALIZE_WITHDEFAULT(JsonName, JsonValue, DefaultJsonValue) \
if (Serializer.IsLoading()) \
{ \
if (!Serializer.GetObject()->HasField(TEXTVIEW(JsonName))) \
{ \
JsonValue = DefaultJsonValue; \
} \
} \
Serializer.Serialize(TEXTVIEW(JsonName), JsonValue);
#define JSON_SERIALIZE_OPTIONAL(JsonName, OptionalJsonValue) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasField(TEXTVIEW(JsonName))) \
{ \
Serializer.Serialize(TEXTVIEW(JsonName), OptionalJsonValue.Emplace()); \
} \
} \
else \
{ \
if (OptionalJsonValue.IsSet()) \
{ \
Serializer.Serialize(TEXTVIEW(JsonName), OptionalJsonValue.GetValue()); \
} \
}
#define JSON_SERIALIZE_OPTIONAL_MAP(JsonName, JsonMap) \
if (Serializer.IsLoading() && !JsonMap.IsSet() && Serializer.GetObject().IsValid() && Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
JsonMap.Emplace(); \
} \
\
if (JsonMap.IsSet()) \
{ \
Serializer.SerializeMap(TEXTVIEW(JsonName), JsonMap.GetValue()); \
}
#define JSON_SERIALIZE_OPTIONAL_ARRAY(JsonName, JsonArray) \
if (Serializer.IsLoading() && !JsonArray.IsSet() && Serializer.GetObject().IsValid() && Serializer.GetObject()->HasTypedField<EJson::Array>(TEXTVIEW(JsonName))) \
{ \
JsonArray.Emplace(); \
} \
\
if (JsonArray.IsSet()) \
{ \
Serializer.SerializeArray(TEXTVIEW(JsonName), JsonArray.GetValue()); \
}
#define JSON_SERIALIZE_ARRAY(JsonName, JsonArray) \
Serializer.SerializeArray(TEXTVIEW(JsonName), JsonArray)
#define JSON_SERIALIZE_ARRAY_WITHDEFAULT(JsonName, JsonArray, DefaultArray) \
if (Serializer.IsLoading()) \
{ \
if (!Serializer.GetObject()->HasField(TEXTVIEW(JsonName))) \
{ \
JsonArray = DefaultArray; \
} \
} \
Serializer.SerializeArray(TEXTVIEW(JsonName), JsonArray);
#define JSON_SERIALIZE_OBJECT_WITHDEFAULT(JsonName, JsonObject, DefaultObject) \
if (Serializer.IsLoading()) \
{ \
if (!Serializer.GetObject()->HasField(TEXTVIEW(JsonName))) \
{ \
JsonObject = DefaultObject; \
} \
} \
Serializer.SerializeArray(TEXTVIEW(JsonName), JsonArray);
#define JSON_SERIALIZE_MAP(JsonName, JsonMap) \
Serializer.SerializeMap(TEXTVIEW(JsonName), JsonMap)
#define JSON_SERIALIZE_SIMPLECOPY(JsonMap) \
Serializer.SerializeSimpleMap(JsonMap)
#define JSON_SERIALIZE_MAP_SAFE(JsonName, JsonMap) \
Serializer.SerializeMapSafe(TEXTVIEW(JsonName), JsonMap)
#define JSON_SERIALIZE_RAW_JSON_STRING(JsonName, JsonValue) \
if (Serializer.IsLoading()) \
{ \
using CharType = TElementType_T<decltype(JsonValue)>; \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObject = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
if (JsonObject.IsValid()) \
{ \
auto Writer = TJsonWriterFactory<CharType, TCondensedJsonPrintPolicy<CharType>>::Create(&JsonValue); \
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer); \
} \
} \
else \
{ \
JsonValue = TString<CharType>(); \
} \
} \
else \
{ \
if (!JsonValue.IsEmpty()) \
{ \
Serializer.WriteIdentifierPrefix(TEXTVIEW(JsonName)); \
Serializer.WriteRawJSONValue(*JsonValue); \
} \
}
#define JSON_SERIALIZE_ARRAY_SERIALIZABLE(JsonName, JsonArray, ElementType) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Array>(TEXTVIEW(JsonName))) \
{ \
for (auto It = Serializer.GetObject()->GetArrayField(TEXTVIEW(JsonName)).CreateConstIterator(); It; ++It) \
{ \
ElementType& Obj = JsonArray.AddDefaulted_GetRef(); \
Obj.FromJson((*It)->AsObject()); \
} \
} \
} \
else \
{ \
Serializer.StartArray(TEXTVIEW(JsonName)); \
for (auto It = JsonArray.CreateIterator(); It; ++It) \
{ \
It->Serialize(Serializer, false); \
} \
Serializer.EndArray(); \
}
#define JSON_SERIALIZE_ARRAY_SERIALIZABLE_WITHDEFAULT(JsonName, JsonArray, ElementType, DefaultArray) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Array>(TEXTVIEW(JsonName))) \
{ \
for (auto It = Serializer.GetObject()->GetArrayField(TEXTVIEW(JsonName)).CreateConstIterator(); It; ++It) \
{ \
ElementType& Obj = JsonArray.AddDefaulted_GetRef(); \
Obj.FromJson((*It)->AsObject()); \
} \
} \
else \
{ \
JsonArray = DefaultArray; \
} \
} \
else \
{ \
Serializer.StartArray(TEXTVIEW(JsonName)); \
for (auto It = JsonArray.CreateIterator(); It; ++It) \
{ \
It->Serialize(Serializer, false); \
} \
Serializer.EndArray(); \
}
#define JSON_SERIALIZE_OPTIONAL_ARRAY_SERIALIZABLE(JsonName, OptionalJsonArray, ElementType) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Array>(TEXTVIEW(JsonName))) \
{ \
TArray<ElementType>& JsonArray = OptionalJsonArray.Emplace(); \
for (auto It = Serializer.GetObject()->GetArrayField(TEXTVIEW(JsonName)).CreateConstIterator(); It; ++It) \
{ \
ElementType& Obj = JsonArray.AddDefaulted_GetRef(); \
Obj.FromJson((*It)->AsObject()); \
} \
} \
} \
else \
{ \
if (OptionalJsonArray.IsSet()) \
{ \
Serializer.StartArray(TEXTVIEW(JsonName)); \
for (auto It = OptionalJsonArray->CreateIterator(); It; ++It) \
{ \
It->Serialize(Serializer, false); \
} \
Serializer.EndArray(); \
} \
}
#define JSON_SERIALIZE_MAP_SERIALIZABLE(JsonName, JsonMap, ElementType) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObj = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
for (auto MapIt = JsonObj->Values.CreateConstIterator(); MapIt; ++MapIt) \
{ \
ElementType NewEntry; \
NewEntry.FromJson(MapIt.Value()->AsObject()); \
JsonMap.Add(MapIt.Key(), NewEntry); \
} \
} \
} \
else \
{ \
Serializer.StartObject(TEXTVIEW(JsonName)); \
for (auto It = JsonMap.CreateIterator(); It; ++It) \
{ \
Serializer.StartObject(MakeStringView(It.Key())); \
It.Value().Serialize(Serializer, true); \
Serializer.EndObject(); \
} \
Serializer.EndObject(); \
}
#define JSON_SERIALIZE_MAP_ARRAY_SERIALIZABLE(JsonName, JsonMap, ElementType) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObj = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
for (auto MapIt = JsonObj->Values.CreateConstIterator(); MapIt; ++MapIt) \
{ \
TArray<ElementType> NewEntry; \
for (auto ArrayIt : MapIt.Value()->AsArray()) \
{ \
NewEntry.Add_GetRef(ElementType()).FromJson(ArrayIt->AsObject()); \
} \
JsonMap.Add(MapIt.Key(), NewEntry); \
} \
} \
} \
else \
{ \
Serializer.StartObject(TEXTVIEW(JsonName)); \
for (auto It = JsonMap.CreateIterator(); It; ++It) \
{ \
Serializer.StartArray(It.Key()); \
for (auto ArrayEntry : It.Value()) \
{ \
ArrayEntry.Serialize(Serializer, false); \
} \
Serializer.EndArray(); \
} \
Serializer.EndObject(); \
}
// Use this to read/write JsonValue with its own keys and values corresponding to its members
#define JSON_SERIALIZE_MEMBERS_OF(JsonValue) \
JsonValue.Serialize(Serializer, /*bIsFlatObject*/true)
#define JSON_SERIALIZE_SERIALIZABLE(JsonName, JsonValue) UE_DEPRECATED_MACRO(5.6, "JSON_SERIALIZE_SERIALIZABLE has been deprecated, use JSON_SERIALIZE_MEMBERS_OF instead") JSON_SERIALIZE_MEMBERS_OF(JsonValue)
// Use this when JsonSerializableObject will be read/write as json object, while JsonName is the key
#define JSON_SERIALIZE_OBJECT_SERIALIZABLE(JsonName, JsonSerializableObject) \
/* Process the JsonName field differently because it is an object */ \
if (Serializer.IsLoading()) \
{ \
/* Read in the value from the JsonName field */ \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObj = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
if (JsonObj.IsValid()) \
{ \
(JsonSerializableObject).FromJson(JsonObj); \
} \
} \
} \
else \
{ \
/* Write the value to the Name field */ \
Serializer.StartObject(TEXTVIEW(JsonName)); \
(JsonSerializableObject).Serialize(Serializer, true); \
Serializer.EndObject(); \
}
#define JSON_SERIALIZE_OBJECT_SERIALIZABLE_WITHDEFAULT(JsonName, JsonSerializableObject, JsonSerializableObjectDefault) \
/* Process the JsonName field differently because it is an object */ \
if (Serializer.IsLoading()) \
{ \
/* Read in the value from the JsonName field */ \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObj = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
if (JsonObj.IsValid()) \
{ \
(JsonSerializableObject).FromJson(JsonObj); \
} \
} \
else \
{ \
JsonSerializableObject = JsonSerializableObjectDefault; \
} \
} \
else \
{ \
/* Write the value to the Name field */ \
Serializer.StartObject(TEXTVIEW(JsonName)); \
(JsonSerializableObject).Serialize(Serializer, true); \
Serializer.EndObject(); \
}
#define JSON_SERIALIZE_OPTIONAL_OBJECT_SERIALIZABLE(JsonName, JsonSerializableObject) \
if (Serializer.IsLoading()) \
{ \
using ObjectType = TRemoveReference<decltype(JsonSerializableObject.GetValue())>::Type; \
if (Serializer.GetObject()->HasTypedField<EJson::Object>(TEXTVIEW(JsonName))) \
{ \
TSharedPtr<FJsonObject> JsonObj = Serializer.GetObject()->GetObjectField(TEXTVIEW(JsonName)); \
if (JsonObj.IsValid()) \
{ \
JsonSerializableObject = ObjectType{}; \
JsonSerializableObject.GetValue().FromJson(JsonObj); \
} \
} \
} \
else \
{ \
if (JsonSerializableObject.IsSet()) \
{ \
Serializer.StartObject(TEXTVIEW(JsonName)); \
(JsonSerializableObject.GetValue()).Serialize(Serializer, true); \
Serializer.EndObject(); \
} \
}
#define JSON_SERIALIZE_DATETIME_UNIX_TIMESTAMP(JsonName, JsonDateTime) \
if (Serializer.IsLoading()) \
{ \
int64 UnixTimestampValue; \
Serializer.Serialize(TEXTVIEW(JsonName), UnixTimestampValue); \
JsonDateTime = FDateTime::FromUnixTimestamp(UnixTimestampValue); \
} \
else \
{ \
int64 UnixTimestampValue = JsonDateTime.ToUnixTimestamp(); \
Serializer.Serialize(TEXTVIEW(JsonName), UnixTimestampValue); \
}
#define JSON_SERIALIZE_DATETIME_UNIX_TIMESTAMP_MILLISECONDS(JsonName, JsonDateTime) \
if (Serializer.IsLoading()) \
{ \
int64 UnixTimestampValueInMilliseconds; \
Serializer.Serialize(TEXTVIEW(JsonName), UnixTimestampValueInMilliseconds); \
JsonDateTime = FDateTime::FromUnixTimestamp(UnixTimestampValueInMilliseconds / 1000); \
} \
else \
{ \
int64 UnixTimestampValueInMilliseconds = JsonDateTime.ToUnixTimestamp() * 1000; \
Serializer.Serialize(TEXTVIEW(JsonName), UnixTimestampValueInMilliseconds); \
}
#define JSON_SERIALIZE_ENUM(JsonName, JsonEnum) \
if (Serializer.IsLoading()) \
{ \
FString JsonTextValue; \
Serializer.Serialize(TEXTVIEW(JsonName), JsonTextValue); \
LexFromString(JsonEnum, *JsonTextValue); \
} \
else \
{ \
FString JsonTextValue = LexToString(JsonEnum); \
Serializer.Serialize(TEXTVIEW(JsonName), JsonTextValue); \
}
#define JSON_SERIALIZE_ENUM_ARRAY(JsonName, JsonArray, EnumType) \
if (Serializer.IsLoading()) \
{ \
if (Serializer.GetObject()->HasTypedField<EJson::Array>(TEXTVIEW(JsonName))) \
{ \
EnumType EnumValue; \
for (auto It = Serializer.GetObject()->GetArrayField(TEXTVIEW(JsonName)).CreateConstIterator(); It; ++It) \
{ \
LexFromString(EnumValue, *(*It)->AsString()); \
JsonArray.Add(EnumValue); \
} \
} \
} \
else \
{ \
Serializer.StartArray(TEXTVIEW(JsonName)); \
for (EnumType& EnumValue : JsonArray) \
{ \
FString JsonTextValue = LexToString(EnumValue); \
Serializer.Serialize(TEXTVIEW(JsonName), JsonTextValue); \
} \
Serializer.EndArray(); \
}