Json数据映射到蓝图Struct

Json数据怎么映射到蓝图了?蓝图的文件都是uasset文件,有点类似二进制的文件,从应用层想把数据进行互相映射,没有提供相应的API,那就另想别的方法,所有的资源运行都在内存中,所以直接从内存中去操作!蓝图的Struct在内存中的映射和代码层的Struct在内存中的映射其实是一样的,数据结构有点类似单向链表,具体的有知道的,麻烦告知一下,不慎感激!

既然有了解决方案,下一步就是代码操作了,代码直接奉上!

​​​​​​​

// Fill out your copyright notice in the Description page of Project Settings.

#include "JsonConverter.h"
#include "Engine/Blueprint.h"
#include "Runtime/CoreUObject/Public/UObject/UnrealType.h"
#include "Engine/UserDefinedStruct.h"

JsonConverter *GetJsonConverter()
{
	static JsonConverter conv;
	return &conv;
}

JsonConverter::JsonConverter()
{
}

JsonConverter::~JsonConverter()
{

}

//---------Json映射到Struct-------------------------
void JsonConverter::ImportJasonToUStruct(const FString &content, UCustomStruct *msgUObject)
{
	if (content.IsEmpty() || msgUObject == nullptr)
	{
		return;
	}
	
	UClass *tmpClass = msgUObject->GetClass();

	UStructProperty *StructProperty = (UStructProperty *)tmpClass->FindPropertyByName(FName(TEXT("Table")));
	if (StructProperty == nullptr)
	{
		return;
	}

	void *StructAddress = StructProperty->ContainerPtrToValuePtr<void>(msgUObject);

	TSharedPtr<FJsonObject> JsonObject;
	TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(content);
	if (FJsonSerializer::Deserialize(Reader, JsonObject))
	{
		TMap<FString, TSharedPtr<FJsonValue>> JsonValues = JsonObject->Values;
		for (auto &Iter: JsonValues)
		{
			UProperty *Property = GetProperty(StructProperty->Struct, Iter.Key);
			if (Property == nullptr)
			{
				continue;
			}
			void* Address = Property->ContainerPtrToValuePtr<void>(StructAddress);
			JsonDataReflectUObjectData(Iter.Key, JsonObject, Iter.Value->Type, Property, Address);
		}
	}
}

void JsonConverter::JsonDataReflectUObjectData(const FString &JsonKey, TSharedPtr<FJsonObject> JsonValue, EJson ValueType, UProperty *Property, void *Address)
{
	if (ValueType == EJson::Null || ValueType == EJson::None || JsonKey.IsEmpty() || !JsonValue.IsValid())
	{
		return;
	}

	switch (ValueType)
	{
		case EJson::Boolean:
		{
			bool value = false;
			if (JsonValue->TryGetBoolField(JsonKey, value))
			{
				((UBoolProperty *)Property)->SetPropertyValue_InContainer(Address, value);
			}
		}
		break;
		case EJson::Number:
		{
			int32 value;
			if (JsonValue->TryGetNumberField(JsonKey, value))
			{
				((UIntProperty *)Property)->SetPropertyValue_InContainer(Address, value);
			}
		}
		break;
		case EJson::String:
		{
			FString StrValue;
			if (JsonValue->TryGetStringField(JsonKey, StrValue))
			{
				//CastChecked<UStrProperty>(Property)->SetPropertyValue_InContainer(Address, StrValue);
				((UStrProperty*)Property)->SetPropertyValue_InContainer(Address, StrValue);
			}
		}
		break;
		case EJson::Array:
		{
			const TArray<TSharedPtr<FJsonValue>> *JsonArray;
			if (JsonValue->TryGetArrayField(JsonKey, JsonArray))
			{
				DeserializeJsonArray(*JsonArray, Property, Address);
			}
		}
		break;
		case EJson::Object:
		{
			const TSharedPtr<FJsonObject>* JsonObject;
			if (JsonValue->TryGetObjectField(JsonKey, JsonObject))
			{
				DeserializeJsonObject(JsonKey, *JsonObject, Property, Address);
			}
		}
		break;
	}
}

void JsonConverter::DeserializeJsonArray(const TArray<TSharedPtr<FJsonValue>> &JsonArray, UProperty *Property, void *StructAddress)
{
	UArrayProperty *ArrProperty = Cast<UArrayProperty>(Property);
	FScriptArrayHelper ArrHelper(ArrProperty, StructAddress);
	ArrHelper.EmptyValues();

	TMap<FString, TSharedPtr<FJsonValue>> JsonValues;
	const TSharedPtr<FJsonObject>* FileMessageObject;
	for (int i = 0; i < JsonArray.Num(); i++)
	{
		if (JsonArray[i].Get()->TryGetObject(FileMessageObject))
		{
			const int32 NewEntryIndex = ArrHelper.AddValue();
			uint8 *EntryAddress = ArrHelper.GetRawPtr(NewEntryIndex);

			JsonValues = (*FileMessageObject)->Values;
			for (auto &Iter : JsonValues)
			{
				if (ArrProperty->Inner->IsA<UStructProperty>())
				{
					UStructProperty *PropertyStruct = Cast<UStructProperty>(ArrProperty->Inner);
					UProperty *Property = GetProperty(PropertyStruct->Struct, Iter.Key);
					JsonDataReflectUObjectData(Iter.Key, *FileMessageObject, Iter.Value->Type, Property, EntryAddress);
				}
			}
		}
	}
}

void JsonConverter::DeserializeJsonObject(const FString &JsonKey, TSharedPtr<FJsonObject> JsonObject, UProperty *Property, void *StructAddress)
{
	if (JsonKey.IsEmpty() || !JsonObject.IsValid())
	{
		return;
	}

	const TArray<TSharedPtr<FJsonValue>> *JsonArray;
	if (!JsonObject->TryGetArrayField(JsonKey, JsonArray))
	{
		return;
	}

	DeserializeJsonArray(*JsonArray, Property, StructAddress);
}

UProperty* JsonConverter::GetProperty(UStruct *StructClass, const FString &Name)
{
	for (UProperty* Property = StructClass->PropertyLink; Property != NULL; Property = Property->PropertyLinkNext)
	{
		if (Property->GetName().Contains(Name))
		{
			return Property;
		}
	}
	return NULL;
}
//-------------------------------------------------


//--------------Struct映射到JsonString-----------------
FString JsonConverter::ExportToJasonFromUStruct(UCustomStruct *msgUObject)
{
	FString JsonString = TEXT("");
	if (msgUObject == nullptr)
	{
		return JsonString;
	}

	UStructProperty *StructProperty = (UStructProperty *)msgUObject->GetClass()->FindPropertyByName(FName(TEXT("Table")));
	void *StructAddress = StructProperty->ContainerPtrToValuePtr<void>(msgUObject);
	if (StructProperty == nullptr)
	{
		return JsonString;
	}

	TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&JsonString);
	JsonWriter->WriteObjectStart();
	UScriptStruct *Struct = StructProperty->Struct;
	for (TFieldIterator<UProperty> It(Struct); It; ++It)
	{
		UProperty *Property = *It;
		FString Name = Property->GetName();

		for (int32 Index = 0; Index < Property->ArrayDim; Index++)
		{
			void *ValuePtr = Property->ContainerPtrToValuePtr<void>(StructAddress, Index);
			{
				ExportChildProperty(Property, JsonWriter, ValuePtr);
			}
		}
	}

	JsonWriter->WriteObjectEnd();
	JsonWriter->Close();

	UE_LOG(LogTemp, Warning, TEXT("JsonString = %s"), *JsonString);
	return JsonString;
}

void JsonConverter::ExportChildProperty(UProperty *Property, TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> &JsonWriter, void *Address)
{
	FString Key = GetPropertyName(Property);
	if (Property->IsA<UBoolProperty>())
	{
		bool Value = ((UBoolProperty *)Property)->GetPropertyValue_InContainer(Address);
		JsonWriter->WriteValue(Key, Value);
	}
	else if (Property->IsA<UInt64Property>() || Property->IsA<UFloatProperty>() || Property->IsA<UUInt32Property>()
		|| Property->IsA<UIntProperty>() || Property->IsA<UDoubleProperty>())
	{
		double Value = ((UIntProperty *)Property)->GetPropertyValue_InContainer(Address);
		UE_LOG(LogTemp, Warning, TEXT("Key = %s   Value = %f"), *Key, Value);
		JsonWriter->WriteValue(Key, Value);
	}
	else if (Property->IsA<UStrProperty>())
	{
		FString Value = ((UStrProperty *)Property)->GetPropertyValue_InContainer(Address);
		UE_LOG(LogTemp, Warning, TEXT("Key = %s   Value = %s"), *Key, *Value);
		JsonWriter->WriteValue(Key, Value);
	}
	else if (Property->IsA<UArrayProperty>())
	{
		UArrayProperty *ArrayProperty = Cast<UArrayProperty>(Property);
		FScriptArrayHelper Helper(ArrayProperty, Address);
		FString Key = GetPropertyName(Property);
		JsonWriter->WriteArrayStart(Key);
		UProperty *CurProperty = nullptr;
		UE_LOG(LogTemp, Warning, TEXT("Number = %d"), Helper.Num());
		for (int32 i = 0; i < Helper.Num(); i++)
		{
			if (ArrayProperty->Inner->IsA<UStructProperty>())
			{
				UStructProperty *PropertyStruct = Cast<UStructProperty>(ArrayProperty->Inner);
				if (PropertyStruct != nullptr)
				{
					JsonWriter->WriteObjectStart();
					UStruct *P = PropertyStruct->Struct;
					void *Address = (void *)Helper.GetRawPtr(i);

					for (UProperty* Property = P->PropertyLink; Property != NULL; Property = Property->PropertyLinkNext)
					{
						ExportChildProperty(Property, JsonWriter, Address);
					}
					JsonWriter->WriteObjectEnd();
				}
			}
		}
		JsonWriter->WriteArrayEnd();
	}
}

FString JsonConverter::GetPropertyName(UProperty *Property)
{
	FString PropertyName = Property->GetName();
	FString Left;
	FString Right;
	if (PropertyName.Split("_", &Left, &Right))
	{
		return Left;
	}

	return "";
}
//-----------------------------------------------------

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值