一些关于Json文件的读写知识
参考:【UE4】文件系统
一、准备
UE中想进行基础的读写Json文件需要引入模块:在.Build.cs文件中添加一行,"Json"
using UnrealBuildTool;
public class PakTest : ModuleRules
{
public PakTest(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"PakFile",
"Json"//,
//"JsonUtilities"//后面会说,基础的读写用不到
});
}
}
二、FJsonObject, FString, 文件
void ALoadPakActor::JsonSerializeTest(const FString& FilePath)
{
TSharedPtr<FJsonObject> rootObj = MakeShareable(new FJsonObject());//首先创建一个FJsonObject对象
rootObj->SetStringField("root", "1");
rootObj->SetBoolField("bIsTest",false);
//rootObj->SetObjectField("secondRoot",rootObj);//Error
TSharedPtr<FJsonObject> SecondRoot = MakeShareable(new FJsonObject());
TSharedPtr<FJsonValue> testValue = MakeShareable(new FJsonValueNumber(8.4));
SecondRoot->SetField("valueKey",testValue);
rootObj->SetObjectField("secondRoot", SecondRoot);
TSharedPtr<FJsonObject> ThirdRoot = MakeShareable(new FJsonObject());
ThirdRoot->SetObjectField("SecondRoot",SecondRoot);//可以重复使用,上面那个不行猜测是循环嵌套
rootObj->SetObjectField("ThirdRoot", ThirdRoot);
TArray<TSharedPtr<FJsonValue>> arrValue;
TSharedPtr<FJsonValueString> tmp = MakeShareable(new FJsonValueString("array"));
arrValue.Add(tmp);
tmp = MakeShareable(new FJsonValueString("9.2"));
arrValue.Add(tmp);
tmp = MakeShareable(new FJsonValueString("9.2adg"));
arrValue.Add(tmp);
arrValue.Add(testValue);//可以重复使用
rootObj->SetArrayField("array", arrValue);
FString jsonStr;
TSharedRef<TJsonWriter<TCHAR>> jsonWriter = TJsonWriterFactory<TCHAR>::Create(&jsonStr);//写入一样需要绑定一个FString作为输入流载体
FJsonSerializer::Serialize(rootObj.ToSharedRef(), jsonWriter);//序列化写好的FJsonObject对象需要转化为FString字符串才能向文本中写入数据
FFileHelper::SaveStringToFile(jsonStr, *FilePath);
UE_LOG(LogTemp, Warning, TEXT("JsonData%s"),*jsonStr);
}
写入之后长这样
{
"root": "1",
"bIsTest": false,
"secondRoot":
{
"valueKey": 8.4000000000000004
},
"ThirdRoot":
{
"SecondRoot":
{
"valueKey": 8.4000000000000004
}
},
"array": [
"array",
"9.2",
"9.2adg",
8.4000000000000004 ]
}
void ALoadPakActor::JsonDeserializeTest(const FString& FilePath)
{
if (FPaths::FileExists(FilePath))
{
FString fileStr;
FFileHelper::LoadFileToString(fileStr, *FilePath);//首先Json文本的读取需要将Json文本以字符串的形式读入到一个FString的输入流载体中
TSharedRef<TJsonReader<>> jsonReader = TJsonReaderFactory<>::Create(fileStr);//然后我们需要将这个输入流载体绑定到TJsonReader<>读出工具上
TSharedPtr<FJsonObject> rootObject = MakeShareable(new FJsonObject());
if (FJsonSerializer::Deserialize(jsonReader, rootObject))//然后将输入流载体的Json数据反序列化到FJsonObject对象中
{
UE_LOG(LogTemp, Warning, TEXT("root:%s"),*rootObject->GetStringField("root"));
UE_LOG(LogTemp, Warning, TEXT("bIsTest:%d"),rootObject->GetBoolField("bIsTest"));
UE_LOG(LogTemp, Warning, TEXT("secondRoot-valueKey:%f"),rootObject->GetObjectField("secondRoot")->GetNumberField("valueKey"));
UE_LOG(LogTemp, Warning, TEXT("ThirdRoot-SecondRoot-valueKey:%f"),rootObject->GetObjectField("ThirdRoot")->GetObjectField("SecondRoot")->GetNumberField("valueKey"));
TArray<TSharedPtr<FJsonValue>> Array;
Array = rootObject->GetArrayField("array");
for (auto JsonValue : Array)
{
//UE_LOG(LogTemp, Warning, TEXT("array:%s"),*JsonValue.Get()->AsString());
UE_LOG(LogTemp, Warning, TEXT("array:%f"),JsonValue.Get()->AsNumber());
}
}
}
}
三、JsonUtilities
这个其实挺常用的,可能常用的有FJsonDomBuilder, FJsonObjectConverter
FJsonDomBuilder让上面构造FJsonObject更方便
/**
* Helpers for creating TSharedPtr<FJsonValue> JSON trees
*
* Simple example:
*
* FJsonDomBuilder::FArray InnerArray;
* InnerArray.Add(7.f, TEXT("Hello"), true);
*
* FJsonDomBuilder::FObject Object;
* Object.Set(TEXT("Array"), InnerArray);
* Object.Set(TEXT("Number"), 13.f);
*
* Object.AsJsonValue();
*
* produces {"Array": [7., "Hello", true], "Number": 13.}
*/
class FJsonDomBuilder
FJsonObjectConverter让FJsonObject和你的结构体转换更方便,简单使用可以下面视频和代码
LoadPakActor.h
USTRUCT(BlueprintType)
struct FMyJsonStruct
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite)
FString Name;
UPROPERTY(BlueprintReadWrite)
int Age;
};
UCLASS()
class PAKTEST_API ALoadPakActor : public AActor
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
FMyJsonStruct ConvertStringToJsonStruct(const FString& JsonContent);
UFUNCTION(BlueprintCallable)
FString ConvertJsonStructToString(const FMyJsonStruct& JsonStruct);
};
LoadPakActor.cpp
FMyJsonStruct ALoadPakActor::ConvertStringToJsonStruct(const FString& JsonContent)
{
FMyJsonStruct MyJsonStruct;
if (!FJsonObjectConverter::JsonObjectStringToUStruct(JsonContent, &MyJsonStruct))
{
UE_LOG(LogTemp, Warning, TEXT("JsonObjectStringToUStruct - Unable to parse json=[%s]"), *JsonContent);
}
return MyJsonStruct;
}
FString ALoadPakActor::ConvertJsonStructToString(const FMyJsonStruct& JsonStruct)
{
FString JsonContent;
if (!FJsonObjectConverter::UStructToJsonObjectString(JsonStruct, JsonContent))
{
UE_LOG(LogTemp, Warning, TEXT("UStructToJsonObjectString - Unable to write out JSON: %s"), *JsonStruct.StaticStruct()->GetName());
JsonContent = "Error";
}
return JsonContent;
}
对应Json文件格式为,并且从蓝图运行情况来看不区分大小写因为UPROPERTY宏做了处理(必须加这个宏,不加无法Convert),但是最好还是养好习惯
{
"name": "李明",
"age": 18
}