本文主要介绍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":.......... }
 
  |