// Copyright Epic Games, Inc. All Rights Reserved. #include "Backends/JsonStructDeserializerBackend.h" #include "Backends/StructDeserializerBackendUtilities.h" #include "UObject/Class.h" #include "UObject/UnrealType.h" #include "UObject/EnumProperty.h" #include "UObject/TextProperty.h" /* IStructDeserializerBackend interface *****************************************************************************/ const FString& FJsonStructDeserializerBackend::GetCurrentPropertyName() const { return JsonReader->GetIdentifier(); } FString FJsonStructDeserializerBackend::GetDebugString() const { return FString::Printf(TEXT("Line: %u, Ch: %u"), JsonReader->GetLineNumber(), JsonReader->GetCharacterNumber()); } const FString& FJsonStructDeserializerBackend::GetLastErrorMessage() const { return JsonReader->GetErrorMessage(); } bool FJsonStructDeserializerBackend::GetNextToken( EStructDeserializerBackendTokens& OutToken ) { if (!JsonReader->ReadNext(LastNotation)) { return false; } switch (LastNotation) { case EJsonNotation::ArrayEnd: OutToken = EStructDeserializerBackendTokens::ArrayEnd; break; case EJsonNotation::ArrayStart: OutToken = EStructDeserializerBackendTokens::ArrayStart; break; case EJsonNotation::Boolean: case EJsonNotation::Null: case EJsonNotation::Number: case EJsonNotation::String: { OutToken = EStructDeserializerBackendTokens::Property; } break; case EJsonNotation::Error: OutToken = EStructDeserializerBackendTokens::Error; break; case EJsonNotation::ObjectEnd: OutToken = EStructDeserializerBackendTokens::StructureEnd; break; case EJsonNotation::ObjectStart: OutToken = EStructDeserializerBackendTokens::StructureStart; break; default: OutToken = EStructDeserializerBackendTokens::None; } return true; } bool FJsonStructDeserializerBackend::ReadProperty( FProperty* Property, FProperty* Outer, void* Data, int32 ArrayIndex ) { switch (LastNotation) { // boolean values case EJsonNotation::Boolean: { bool BoolValue = JsonReader->GetValueAsBoolean(); if (FBoolProperty* BoolProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(BoolProperty, Outer, Data, ArrayIndex, BoolValue); } const FCoreTexts& CoreTexts = FCoreTexts::Get(); UE_LOG(LogSerialization, Verbose, TEXT("Boolean field %s with value '%s' is not supported in FProperty type %s (%s)"), *Property->GetFName().ToString(), BoolValue ? *(CoreTexts.True.ToString()) : *(CoreTexts.False.ToString()), *Property->GetClass()->GetName(), *GetDebugString()); return false; } // numeric values case EJsonNotation::Number: { const FString& NumericValueString = JsonReader->GetValueAsNumberString(); if (FByteProperty* ByteProperty = CastField(Property)) { int8 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(ByteProperty, Outer, Data, ArrayIndex, NumericValue); } } if (FDoubleProperty* DoubleProperty = CastField(Property)) { double NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(DoubleProperty, Outer, Data, ArrayIndex, NumericValue); } } if (FFloatProperty* FloatProperty = CastField(Property)) { float NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(FloatProperty, Outer, Data, ArrayIndex, NumericValue); } } if (FIntProperty* IntProperty = CastField(Property)) { int32 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(IntProperty, Outer, Data, ArrayIndex, NumericValue); } } if (FUInt32Property* UInt32Property = CastField(Property)) { uint32 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(UInt32Property, Outer, Data, ArrayIndex, NumericValue); } } if (FInt16Property* Int16Property = CastField(Property)) { int16 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(Int16Property, Outer, Data, ArrayIndex, NumericValue); } } if (FUInt16Property* FInt16Property = CastField(Property)) { uint16 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(FInt16Property, Outer, Data, ArrayIndex, NumericValue); } } if (FInt64Property* Int64Property = CastField(Property)) { int64 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(Int64Property, Outer, Data, ArrayIndex, NumericValue); } } if (FUInt64Property* FInt64Property = CastField(Property)) { uint64 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(FInt64Property, Outer, Data, ArrayIndex, NumericValue); } } if (FInt8Property* Int8Property = CastField(Property)) { int8 NumericValue = 0; if (LexTryParseString(NumericValue, *NumericValueString)) { return StructDeserializerBackendUtilities::SetPropertyValue(Int8Property, Outer, Data, ArrayIndex, NumericValue); } } UE_LOG(LogSerialization, Verbose, TEXT("Numeric field %s with value '%s' is not supported in FProperty type %s (%s)"), *Property->GetFName().ToString(), *NumericValueString, *Property->GetClass()->GetName(), *GetDebugString()); return false; } // null values case EJsonNotation::Null: return StructDeserializerBackendUtilities::ClearPropertyValue(Property, Outer, Data, ArrayIndex); // strings, names, enumerations & object/class reference case EJsonNotation::String: { const FString& StringValue = JsonReader->GetValueAsString(); if (FStrProperty* StrProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(StrProperty, Outer, Data, ArrayIndex, StringValue); } if (FNameProperty* NameProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(NameProperty, Outer, Data, ArrayIndex, FName(*StringValue)); } if (FTextProperty* TextProperty = CastField(Property)) { FText TextValue; if (!FTextStringHelper::ReadFromBuffer(*StringValue, TextValue)) { TextValue = FText::FromString(StringValue); } return StructDeserializerBackendUtilities::SetPropertyValue(TextProperty, Outer, Data, ArrayIndex, TextValue); } if (FByteProperty* ByteProperty = CastField(Property)) { if (!ByteProperty->Enum) { return false; } int64 Value = ByteProperty->Enum->GetValueByName(*StringValue); if (Value == INDEX_NONE) { return false; } return StructDeserializerBackendUtilities::SetPropertyValue(ByteProperty, Outer, Data, ArrayIndex, (uint8)Value); } if (FEnumProperty* EnumProperty = CastField(Property)) { int64 Value = EnumProperty->GetEnum()->GetValueByName(*StringValue); if (Value == INDEX_NONE) { return false; } if (void* ElementPtr = StructDeserializerBackendUtilities::GetPropertyValuePtr(EnumProperty, Outer, Data, ArrayIndex)) { EnumProperty->GetUnderlyingProperty()->SetIntPropertyValue(ElementPtr, Value); return true; } return false; } if (FClassProperty* ClassProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(ClassProperty, Outer, Data, ArrayIndex, LoadObject(nullptr, *StringValue, nullptr, LOAD_NoWarn)); } if (FSoftClassProperty* SoftClassProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(SoftClassProperty, Outer, Data, ArrayIndex, FSoftObjectPtr(LoadObject(nullptr, *StringValue, nullptr, LOAD_NoWarn))); } if (FObjectProperty* ObjectProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(ObjectProperty, Outer, Data, ArrayIndex, StaticFindObject(ObjectProperty->PropertyClass, nullptr, *StringValue)); } if (FWeakObjectProperty* WeakObjectProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(WeakObjectProperty, Outer, Data, ArrayIndex, FWeakObjectPtr(StaticFindObject(WeakObjectProperty->PropertyClass, nullptr, *StringValue))); } if (FSoftObjectProperty* SoftObjectProperty = CastField(Property)) { return StructDeserializerBackendUtilities::SetPropertyValue(SoftObjectProperty, Outer, Data, ArrayIndex, FSoftObjectPtr(FSoftObjectPath(StringValue))); } UE_LOG(LogSerialization, Verbose, TEXT("String field %s with value '%s' is not supported in FProperty type %s (%s)"), *Property->GetFName().ToString(), *StringValue, *Property->GetClass()->GetName(), *GetDebugString()); return false; } } return true; } void FJsonStructDeserializerBackend::SkipArray() { JsonReader->SkipArray(); } void FJsonStructDeserializerBackend::SkipStructure() { JsonReader->SkipObject(); }