本文主要介绍UE4下的JSON文件的读写
文件读写
首先我们需要扩展普通的文件读写方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool UTestLib::V_LoadStringFromFile(const FString& FileName, const FString& RelativePath, FString& result) { if (!FileName.IsEmpty()) { FString file=FPaths::ProjectContentDir()+RelativePath+FileName; return FFileHelper::LoadFileToString(result,*file); } return false; } bool UTestLib::V_SaveStringToFile(const FString& FileName, const FString& RelativePath, const FString& string) {
if (!FileName.IsEmpty()) { FString file = FPaths::ProjectContentDir() + RelativePath + FileName; return FFileHelper::SaveStringToFile(string,*file);
} return false; }
|
此方法是以工程目录下的Content路径为基础的,如果需要指定其他路径就需要替换 FPaths::ProjectContentDir()
方法或者干脆直接把整个路径给公开
JSON文件读写
先来一个示例JSON
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { "school": "Super", "name": [ "Tom", "Jien", "Harry" ], "Tom": { "sex":"boy", "score": { "Math":99, "English":80 } }, "Jien": { "sex":"boy", "score": { "Math":88, "English":95 } } }
|
解释几个关键参数
1 2
| TSharedPtr<FJsonObject> JSONContentObject; TSharedRef<TJsonReader<TCHAR>> Reader = TJsonReaderFactory<TCHAR>::Create(JSONInput);
|
用来反序列化的一个类,把文件中的字符串先存放到TJsonReader
的智能指针里;同样的还有写入操作和序列化操作,对应的类就是TJsonWriter
1
| FJsonSerializer::Deserialize(Reader, JSONContentObject)
|
通过FJsonSerializer
把TJsonReader
反序列化到FJsonObject
中,然后就可以通过方法来解读
1
| StringValue=JSONContentObject->GetStringField(key);
|
当然,有个前提是这个key对应的一个值,如示例中的"school": "Super
因为JSON文件是可以使用数组和嵌套的,对于数组,就必须用到FJsonValue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
TArray<TSharedPtr<FJsonValue>> JsonParedValue; TSharedPtr<FJsonObject> JsonObj; if (FJsonSerializer::Deserialize(JsonReader, JsonObj)) { JsonParedValue = JsonObj->GetArrayField(key); }
|
因为name
对应的是一个数组,所以得到的FJsonValue
就是这个数组的成员
然后通过下面方法得到所有成员
1 2 3 4
| for (auto i: JsonParedValue) { value.Add(i->AsString()); }
|
完整的解析一个键值对,值是数组的方法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| bool UTestLib::V_LoadValueArrayFromJsonKey(const FString& JsonString, const FString& key, TArray<FString>& value) { TArray<TSharedPtr<FJsonValue>> JsonParedValue; TSharedPtr<FJsonObject> JsonObj; TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonString); if (FJsonSerializer::Deserialize(JsonReader, JsonObj)) { JsonParedValue = JsonObj->GetArrayField(key); for (auto i: JsonParedValue) { value.Add(i->AsString()); } return true; } return false; }
|
简单的键值对的方法如下
1 2 3 4 5 6 7 8 9 10 11 12
| bool UTestLib::V_LoadValueFromJsonKey(const FString& JsonString, const FString& key, FString& value) { TArray<TSharedPtr<FJsonValue>> JsonParedValue; TSharedPtr<FJsonObject> JsonObj; TSharedRef<TJsonReader<TCHAR>> JsonReader=TJsonReaderFactory<TCHAR>::Create(JsonString); if (FJsonSerializer::Deserialize(JsonReader, JsonObj)) { value=JsonObj->GetStringField(key); return true; } return false; }
|
写入会麻烦一点,首先需要些一个函数来把FJsonObject
转换为FString
1 2 3 4 5 6 7 8 9 10
| bool UTestLib::GetStringFromJsonObj(const TSharedPtr<FJsonObject>& InJsonObj, FString& OutStr) { if (InJsonObj.IsValid() && InJsonObj->Values.Num() > 0) { TSharedRef<TJsonWriter<TCHAR>> t_writer = TJsonWriterFactory<>::Create(&OutStr); FJsonSerializer::Serialize(InJsonObj.ToSharedRef(), t_writer); return true; } return false; }
|
然后我们直接写一个改写固定键值对的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool UTestLib::V_SaveJsonData(const FString& FileName, const FString& RelativePath, const FString& key, const FString& value) { FString JsonString; FString result; if (V_LoadStringFromFile(FileName, RelativePath, JsonString)) { TArray<TSharedPtr<FJsonValue>> JsonParedValue; TSharedPtr<FJsonObject> JsonObj; TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonString); if (FJsonSerializer::Deserialize(JsonReader, JsonObj)) { JsonObj->SetStringField(key,value); if (GetStringFromJsonObj(JsonObj, result)) { return V_SaveStringToFile(FileName, RelativePath, result); } } } return false;
}
|
最后得到结果
1 2 3 4 5 6 7 8 9 10 11
| \ { "school": "hello", "name": [ "Tom", "Jien", "Harry" ], "Tom":.......... }
|