一、準備工作
如果我們想要在UE4中讀寫Json文件,那麼我們必須使UE4包含Json和JsonUtilities這兩個模塊,那麼UE4如何添加模塊呢?
UE4添加預定義模塊的方法很簡單,我只需打開工程的.Biuld.cs文件,在其中的PublicDependencyModuleNames.AddRange()
函數中追加兩個模塊即可,如:
using UnrealBuildTool;
public class DATA_sys : ModuleRules
{
public DATA_sys(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" ,"Json","JsonUtilities"});
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
如果我們要添加自定義模塊就有點麻煩了,當然這裏就不贅述了。
包含這兩個模塊之後,我們還需要用到 Json.h、JsonObject.h、JsonSerializer.h三個頭文件,其中JsonSerializer.h是用於Json序列化與反序列化用的。
至此我們就可以使用UE4自帶的工具進行Json文件的讀寫工作了。
二、Json文件寫
1.非序列化寫入
void AMysqlJsonCpp::CreatJson()
{
FString filePath = FPaths::GameContentDir() + TEXT("MysqlConfig/Connect.json");
FString jsonStr;
TSharedRef<TJsonWriter<>> jsonWriter = TJsonWriterFactory<>::Create(&jsonStr);
jsonWriter->WriteObjectStart();
jsonWriter->WriteValue(TEXT("server"), TEXT("127.0.0.1"));
jsonWriter->WriteObjectEnd();
jsonWriter->Close();
FFileHelper::SaveStringToFile(jsonStr, *filePath);
}
-
FPaths::GameContentDir()
返回當前工程目錄的Content文件夾的路徑,FPaths爲UE4的路徑讀寫工具; -
FString jsonStr
的作用是用於關聯UE4的Json寫工具TJsonWriter<>,作爲輸入流載體,且JsonStr必須是FString類型; -
TShareRef<T>
是UE4自身的共享指針類型; -
TJsonWriter<>
是UE4專門用於寫Json的模板類,其中類型參數通常爲TCHAR,其中有多個方法供開發者使用:函數 作用 Close() 關閉寫工具 WriterArrayStart() 開始一個Json數組 WriterArrayEnd() 結束一個Json數組 WriterNull(FString) 爲一個鍵寫一個空值 WriterObjectStart() 開始一個Json對象 WriterObjectEnd() 結束一個Json對象 WriterValue(FString,FString/int32/float/bool) 向Json文件寫入鍵值對 -
TJsonWriterFactory<>::Create(FString)
是UE4用來生成Json寫工具TJsonWriter<>的類,TJsonFactory<>只有一個方法就是Create; -
FFileHelper
UE4的文件讀寫工具,方法SaveStringToFile(TJsonWriter*,FString*)
函數的作用就是將Json寫工具中的Json數據寫到FString字符串中的路徑文件中。
使用非序列化方式寫入Json時,寫入方式需要嚴格按照Json的語法格式來做,如最開始需要使用WriterObjectStart()創建一個根前括號,即Json語法中最外面一層的{
,所有寫入結束後需要使用WriterObjectEnd()聲明根對象結束,即Json語法中的最外面一層的}
,同理數組也需要按對象一樣的方法進行處理。如此才能寫入一個結構完整的Json文本。
2.序列化寫入
void AMyActor::Test()
{
TSharedPtr<FJsonObject> rootObj = MakeShareable(new FJsonObject());
rootObj->SetStringField("root", "1");
TArray<TSharedPtr<FJsonValue>> arrValue;
TSharedPtr<FJsonValueString> tmp = MakeShareable(new FJsonValueString("array"));
arrValue.Add(tmp);
rootObj->SetArrayField("array", arrValue);
FString filePath = FPaths::GameContentDir() + TEXT("MysqlConfig/text.json");
FString jsonStr;
TSharedRef<TJsonWriter<TCHAR>> jsonWriter = TJsonWriterFactory<TCHAR>::Create(&jsonStr);
FJsonSerializer::Serialize(rootObj.ToSharedRef(), jsonWriter);
FFileHelper::SaveStringToFile(jsonStr, *filePath);
UE_LOG(LogTemp, Error, TEXT("%s"),*filePath);
}
序列化的寫入方式則無需考慮按Json的語法結構進行寫入,序列化的寫入方式是通過一個FJsonObject對象進行Json文本的寫入。
- 首先使用MakeSahreable()函數創建一個FJsonObject對象並使用共享指針引用。
- 然後我們便可以使用FJsonObject對象中的
SetArrayField(FString,TArray<FSharePtr<FJsonValue>>)
、SetBoolFiled(FString,bool)
、SetNumberField(FString,Number)
、SetStringField(FString,FString)
、SetObjectField(FString,TSharePtr<FJsonObject>)
、SetField(FString,TSharePtr<FJsonValue>)
等函數向FJsonObject對象中寫分別入數組、bool值、數字、字符串、對象和Json鍵值對。其中數組的寫入較爲麻煩,我們需要先向創建Json鍵值對類型共享指針的TArray數組TArray<TSharePtr<FJsonValue>>
。並向數組中添加指向FJsonValue對象的共享指針後然後纔可以使用SetArrayField進行數組的Json文本寫入。 - 我們序列化寫好的FJsonObject對象需要轉化爲FString字符串才能向文本中寫入數據,FJsonObject轉化爲FString輸入流的方式就是
FJsonSerializer::Serialize(TSharePtr<FJsonObject>.ToShareRef(),TSharePtr<FJsonWriter>)
;其中TSharePtr<FJsonWriter>
和非序列化寫入一樣需要綁定一個FString作爲輸入流載體。 - 最後就可以通過FFileHelper::SaveStringToFile(FString,*FString),前一個FString是輸入流載體,後一個*FString是Json文件的存儲路徑。
三、Json文件讀
1.反序列化讀取
TArray<FName> AMysqlJsonCpp::ReadMysqlConnectConfig()
{
FString filePath = FPaths::GameContentDir() + TEXT("MysqlConfig/Connect.json");
if (FPaths::FileExists(filePath))
{
FString server;
FString dbName;
FString userId;
FString passwd;
TArray<FName> connectConfig;
FString fileStr;
FFileHelper::LoadFileToString(fileStr, *filePath);
TSharedPtr<FJsonObject> rootObject = MakeShareable(new FJsonObject());
TSharedRef<TJsonReader<>> jsonReader = TJsonReaderFactory<>::Create(fileStr);
if (FJsonSerializer::Deserialize(jsonReader, rootObject))
{
server = rootObject->GetStringField("server");
dbName = rootObject->GetStringField("dbName");
userId = rootObject->GetStringField("userId");
passwd = rootObject->GetStringField("passwd");
}
connectConfig.Add(FName(*server));
connectConfig.Add(FName(*dbName));
connectConfig.Add(FName(*userId));
connectConfig.Add(FName(*passwd));
}
return TArray<FName>();
}
- 首先Json文本的讀取需要將Json文本以字符串的形式讀入到一個FString的輸入流載體中;
- 然後我們需要將這個輸入流載體綁定到TJsonReader<>讀出工具上;
- 然後使用
FJsonSerializer::Deserialize(TSharePtr<TJsonReader<>>,TSahrePtr<FJsonObject>)
將輸入流載體的Json數據反序列化到FJsonObject對象中; - 最後我們就可以使用FJsonObject對象中的
GetArrayField(FString)
、GetBoolFiled(FString)
、GetNumberField(FString)
、GetStringField(FString)
、GetObjectField(FString)
、GetField(FString)
等方法從Json對象中讀取指定鍵的值了。