UE4 序列化,反序列化,读写 Json

来源:互联网 发布:金字塔软件回测 编辑:程序博客网 时间:2024/05/16 15:20

参考文档:

http://www.wraiyth.com/?p=198   //create and serialize Json in UE4. 

http://www.wraiyth.com/?p=222  //deserialize Json in UE4

//文件管理操作(包括路径)(读写普通的文件,二进制文件)

https://wiki.unrealengine.com/File_Management,_Create_Folders,_Delete_Files,_and_More

 

源代码路径:

Engine-Source-Runtime-Json;

Engine-Source-Runtime-JsonUtilities;

 

//路径,读写文件工具类

FPaths,FFileHelper


注意:

1.类型只能为:bool;number;FString;

2.TSharedPtr<FJsonObject>t_ptr;需要先判断共享指针是否为空,再判断里面是否有值:

比如:if (_ptrJsonObj.IsValid()&&_ptrJsonObj->Values.Num()>0);注意前面为点,空面为指针。

3.存取路径文件时,需要先判断是否已经存在。


序列化:

1.在build.s里加入两个模块:Json and JsonUtilities。

2.建立主要的JsonObject:

TSharedPtr<FJsonObject> t_jsonObject = MakeShareable(new FJsonObject);

3.分别加入基本的三个数据,按键值对的方式:

  t_jsonObject->SetBoolField("userBool",true);

t_jsonObject->SetStringField("userName",_data.m_userName);

t_jsonObject->SetNumberField("userId", _data.m_userIndex);

 

可以是嵌套的单个JsonObject:

TSharedPtr<FJsonObject> t_insideObj = MakeShareable(new FJsonObject);

t_jsonObject->SetObjectField("insideObj",t_insideObj );

嵌套的多个object数组:

TArray<TSharedPtr<FJsonValue>> t_objects;

TSharedPtr<FJsonValueObject>t_objValue=MakeShareable(newFJsonValueObject(t_insideObj));

t_objects.Add(t_objValue);

也可以是别的类型的FJsonValue,混合都可以。

 

可以是数组:

TArray<TSharedPtr<FJsonValue>> _res;

  for (int i = 0; i < t_datasNum;i++)

  {

    TSharedPtr<FJsonValueNumber> t_value = MakeShareable(new FJsonValueNumber(_datas[i]));

    _res.Add(t_value);

}


4.最后得到的FJsonObject转换成Json格式的FString

    

bool ADrawHouseManager::GetFStringInJsonFormat(const TSharedPtr<FJsonObject> &_ptrJsonObj, FString &_strGet){if (_ptrJsonObj.IsValid()&&_ptrJsonObj->Values.Num()>0){TSharedRef<TJsonWriter<TCHAR>> t_writer = TJsonWriterFactory<>::Create(&_strGet);FJsonSerializer::Serialize(_ptrJsonObj.ToSharedRef(), t_writer);return true;}return false;}

 

5.得到的字符串可以存储为多种类型的文件,但内容格式还是Json的。

bool ADrawHouseManager::WriteFileWithJsonData(const FString &_jsonStr, const FString &_fileName){if (!_jsonStr.IsEmpty()){if (!_fileName.IsEmpty()){FString t_path = FPaths::GameContentDir() + "/"+_fileName+".json";if (!FPaths::FileExists(t_path)){if (FFileHelper::SaveStringToFile(_jsonStr, *t_path)){UE_LOG(LogTemp, Warning, TEXT("ADrawHouseManager::WriteTextFileWithJsonData---Save file : %s successfully!!!!path:  %s"), *_fileName, *t_path);return true;}else{UE_LOG(LogTemp,Error,TEXT("ADrawHouseManager::WriteTextFileWithJsonData---Save file : %s failed!!!!path:  %s"), *_fileName,*t_path);}}}}return false;}

 

反序列化:

步骤和上面的差不多,只不过set的函数换成了get

只有一个注意的:t_obj->GetField<EJson::Object>("position");取这个FJsonValue类型的值,因为FJsonValue是其他类型的基类,所以类型不同时根据模板来解析不同类型的数据。

//读取Json字符串

bool ADrawHouseManager::GetJsonObjectFromJsonFString(const FString &_jsonFString, TSharedPtr<FJsonObject> &_jsonObject){if (!_jsonFString.IsEmpty()){TSharedRef<TJsonReader<>> t_reader = TJsonReaderFactory<>::Create(_jsonFString);if (FJsonSerializer::Deserialize(t_reader,_jsonObject)){UE_LOG(LogTemp,Warning,TEXT("ADrawHouseManager::GetJsonObjectFromJsonFString---Read JsonObject from Json FString successfully!!!"));return true;}}return false;}

//读取文件

bool ADrawHouseManager::LoadFStringFromFile(const FString &_fileName,const FString &_fromatStr,FString &_resultStr){if (!_fileName.IsEmpty()){FString t_path = FPaths::GamePluginsDir() + "DrawHouse/SaveData/" + _fileName + _fromatStr;if (FPaths::FileExists(t_path)){if (FFileHelper::LoadFileToString(_resultStr, *t_path)){UE_LOG(LogTemp, Warning, TEXT("ADrawHouseManager::LoadFStringFromFile---load file : %s successfully!!!!path:  %s"), *_fileName, *t_path);return true;}else{UE_LOG(LogTemp, Error, TEXT("ADrawHouseManager::LoadFStringFromFile---load file : %s failed!!!!path:  %s"), *_fileName, *t_path);}}else{UE_LOG(LogTemp, Error, TEXT("ADrawHouseManager::LoadFStringFromFile---load file : %s failed!!!!path:  %s"), *_fileName, *t_path);}}return false;}

 

另外注意点:

1.文件路径的字符串获取除了自己定义绝对路径之外,可以根据FPaths类里的静态函数获取不同类型的路径,然后和自己的文件名和文件后缀拼接。

2.不要忘记存储文件时的检测文件是否已经存在和路径是否正确。


部分序列化:

TSharedPtr<FJsonObject> ADrawHouseManager::SerializeDataToJson(FDrawHouseManagerStoredData &_data){TSharedPtr<FJsonObject> t_jsonObject = MakeShareable(new FJsonObject);if (_data.IsValid()){t_jsonObject->SetBoolField("userBool",true);t_jsonObject->SetStringField("userName",_data.m_userName);t_jsonObject->SetNumberField("userId", _data.m_userIndex);t_jsonObject->SetNumberField("lastWallPointId", _data.m_lastWallPointId);t_jsonObject->SetNumberField("lastWallId", _data.m_lastWallId);t_jsonObject->SetNumberField("lastCloseAreaId", _data.m_lastCloseAreaId);t_jsonObject->SetObjectField("wallPointsData", SerializeWallPointDataToJson(_data.m_wallPointDatas));t_jsonObject->SetObjectField("wallsData", SerializeWallDataToJson(_data.m_wallDatas));t_jsonObject->SetObjectField("closeAreasData", SerializeCloseAreaToJson(_data.m_closeAreaDatas));}else{UE_LOG(LogTemp,Error,TEXT("ADrawHouseManager::SerializeDataToJson---data is invalid!!!"));}return t_jsonObject;}TSharedPtr<FJsonObject> ADrawHouseManager::SerializeWallPointDataToJson(TMap<int, FWallPointStoredData> &_data){TSharedPtr<FJsonObject> t_jsonObject = MakeShareable(new FJsonObject);if (_data.Num()>0){TArray<TSharedPtr<FJsonValue>> t_objects;for (auto it:_data){FWallPointStoredData t_data = it.Value;if (t_data.IsValid()){TSharedPtr<FJsonObject> t_obj = MakeShareable(new FJsonObject);t_obj->SetNumberField("id", t_data.m_id);FVector t_pos = t_data.m_position;t_obj->SetField("position", ULcq_BlueprintFunctionLibrary::GetJsonObjectValueFromXYZ(t_pos.X, t_pos.Y,t_pos.Z));t_obj->SetArrayField("wallPointIds", ULcq_BlueprintFunctionLibrary::GetJsonValueArrayFromIntArray(t_data.m_wallPointsRelativeIds));t_obj->SetArrayField("wallIds", ULcq_BlueprintFunctionLibrary::GetJsonValueArrayFromIntArray(t_data.m_wallRelativeIds));t_obj->SetArrayField("closeAreaIds", ULcq_BlueprintFunctionLibrary::GetJsonValueArrayFromIntArray(t_data.m_closeAreaRelativeIds));TSharedPtr<FJsonValueObject> t_objValue = MakeShareable(new FJsonValueObject(t_obj));t_objects.Add(t_objValue);}else{UE_LOG(LogTemp, Error, TEXT("ADrawHouseManager::SerializeWallPointDataToJson---下标为%d的wall point data is invalid!!!"),it.Key);}}t_jsonObject->SetArrayField("datas", t_objects);}return t_jsonObject;}

部分反序列化:


bool ADrawHouseManager::DeserializeDataFromJson(const TSharedPtr<FJsonObject> &_jsonObject, FDrawHouseManagerStoredData &_data){if (_jsonObject->Values.Num()>0){_data.m_userName=_jsonObject->GetStringField("userName");_data.m_userIndex = _jsonObject->GetNumberField("userId");_data.m_lastWallPointId = _jsonObject->GetNumberField("lastWallPointId");_data.m_lastWallId = _jsonObject->GetNumberField("lastWallId");_data.m_lastCloseAreaId = _jsonObject->GetNumberField("lastCloseAreaId");bool t_res= DeserializeWallPointDataFromJson(_jsonObject->GetObjectField("wallPointsData"), _data.m_wallPointDatas);t_res=DeserializeWallDataFromJson(_jsonObject->GetObjectField("wallsData"), _data.m_wallDatas);t_res=DeserializeCloseAreaFromJson(_jsonObject->GetObjectField("closeAreasData"), _data.m_closeAreaDatas);return t_res;}return false;}


bool ADrawHouseManager::DeserializeWallPointDataFromJson(const TSharedPtr<FJsonObject> &_jsonObject, TMap<int, FWallPointStoredData> &_wallPointDatas){if _jsonObject.IsValid()&&_jsonObject->Values.Num()>0){TArray<TSharedPtr<FJsonValue>> t_objects;t_objects = _jsonObject->GetArrayField("datas");int t_objectsNum = t_objects.Num();if (t_objectsNum>0){for (int i=0;i<t_objectsNum;i++){TSharedPtr<FJsonObject> t_obj = t_objects[i]->AsObject();if (t_obj->Values.Num()>0){FWallPointStoredData t_data;int t_id = t_obj->GetNumberField("id");t_data.m_id = t_id;ULcq_BlueprintFunctionLibrary::GetXYZFromJsonValueObject(t_obj->GetField<EJson::Object>("position"),t_data.m_position.X,t_data.m_position.Y,t_data.m_position.Z);ULcq_BlueprintFunctionLibrary::GetIntArrayFromJsonJsonValueArray(t_obj->GetArrayField("wallPointIds"),t_data.m_wallPointsRelativeIds);ULcq_BlueprintFunctionLibrary::GetIntArrayFromJsonJsonValueArray(t_obj->GetArrayField("wallIds"), t_data.m_wallRelativeIds);ULcq_BlueprintFunctionLibrary::GetIntArrayFromJsonJsonValueArray(t_obj->GetArrayField("closeAreaIds"), t_data.m_closeAreaRelativeIds);_wallPointDatas.Add(t_id,t_data);}else{UE_LOG(LogTemp, Error, TEXT("ADrawHouseManager::DeserializeWallPointDataFromJson---Json wall point data [%d] is invalid!!!"),i);}}return _wallPointDatas.Num() > 0;}}return false;}


Json文件:


object为花括号里的;ArrayFiled的为中括号里的。