
- ???♂? 作者:海碼007
- ?? 專欄:UE虛幻引擎專欄
- ?? 標(biāo)題:【程序員必備】UE4 C++ 虛幻引擎:詳解JSON文件讀、寫、解析,打造高效開發(fā)!
- ?? 寄語:人生的意義或許可以發(fā)揮自己全部的潛力,所以加油吧!
- ?? 最后:文章作者技術(shù)和水平有限,如果文中出現(xiàn)錯(cuò)誤,希望大家能指正
0 應(yīng)用場(chǎng)景
在游戲開發(fā)中,Json 文件常被用來保存游戲數(shù)據(jù)或配置參數(shù),如把游戲?qū)ο蟮膬?nèi)部狀態(tài)存儲(chǔ)到磁盤文件,即序列化游戲?qū)ο蟮臅r(shí)候,或在文件中配置一些游戲相關(guān)的參數(shù)時(shí)。本文將詳細(xì)講解如何在 UE 中讀取與解析 Json 文件。
1 功能前瞻
創(chuàng)建一個(gè) JSONFileReadWrite 類,兩個(gè)成員函數(shù) ReadJSONFileByFN、WriteJSONFile。功能分別是讀取一個(gè) JSON 格式的文件,并可以解析其中數(shù)據(jù);另一個(gè)功能是寫入一個(gè) JSON 文件。
1.1JSON格式介紹
{
"Game": "LOL",
"Year": 2023,
"Judge":
{
"name": "Uzi",
"age": 26,
},
"Player": [
{
"name": "xiaoming",
"levels": 22
},
{
"name": "xiaohu",
"levels": 23
}
]
}
普通類型的值:Json數(shù)據(jù)格式就是一種嵌套的關(guān)系,花括號(hào)里面其實(shí)就是保存了一個(gè)個(gè)鍵值對(duì)(學(xué)過C++map容器應(yīng)該很好理解)例如,Game和Year就是Key鍵,“LOL”、2023就是對(duì)應(yīng)的值,只不過一個(gè)是字符串類型,一個(gè)是整數(shù)類型。
"Game": "LOL",
"Year": 2023,
Json對(duì)象類型的值:當(dāng)然也可以是一個(gè)Json對(duì)象類型,如下Judge的值就是一個(gè)花括號(hào)包裹住的類型,也就是一個(gè)Json對(duì)象。
"Judge":
{
"name": "Uzi",
"age": 26,
},
數(shù)組類型的值:如下所示,Player的值是由 [ ] 包圍住,其中數(shù)組是Json對(duì)象類型
"Player": [
{
"name": "xiaoming",
"levels": 22
},
{
"name": "xiaohu",
"levels": 23
}
]
2 功能實(shí)現(xiàn)
在了解Json數(shù)據(jù)的基本格式后,就可以對(duì)其進(jìn)行讀寫操作。
2.1 準(zhǔn)備工作
創(chuàng)建一個(gè)UE C++工程,并新建一個(gè)JSONFileReadWrite類繼承UObject類,創(chuàng)建兩個(gè)函數(shù),并且讓這個(gè)C++類和成員函數(shù)可以被藍(lán)圖調(diào)用(加入說明符即可)。
// 類是使用BlueprintType將其暴露給藍(lán)圖使用
UCLASS(BlueprintType)
class CPP_API UJSONFileReadWrite : public UObject
{
GENERATED_BODY()
public:
// 函數(shù)是使用BlueprintCallable將其暴露給藍(lán)圖使用
UFUNCTION(BlueprintCallable)
void ReadJSONFileByFN();
UFUNCTION(BlueprintCallable)
void WriteJSONFile();
};
2.2 注意事項(xiàng)
使用UE的Json功能時(shí),需要在build.cs文件中添加Json模塊依賴,不然編譯不通過。
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Json" });
2.3 具體功能實(shí)現(xiàn)
2.3.1 ReadJSONFileByFN函數(shù)實(shí)現(xiàn)
大致思路
- 讀取磁盤中的 JSON 文件,使用 FFileHelper::LoadFileToString 函數(shù)將文件內(nèi)容讀取到FString類型的變量中;
- 將 FString 變量存儲(chǔ)到一個(gè) FJsonObject 變量中;
- 讀取FJsonObject 對(duì)象中的數(shù)據(jù);
【提示】使用文件選擇對(duì)話框需要下面兩個(gè)頭文件
#include "Developer/DesktopPlatform/Public/IDesktopPlatform.h"
#include "Developer/DesktopPlatform/Public/DesktopPlatformModule.h"
#include "Developer/DesktopPlatform/Public/IDesktopPlatform.h"
#include "Developer/DesktopPlatform/Public/DesktopPlatformModule.h"
void UJSONFileReadWrite::ReadJSONFileByFN()
{
//-----------------------------------------------------------------------------------------------------------------
//1.1 選擇磁盤中的Json文件,并獲取Json文件絕對(duì)路徑
TArray<FString> JsonFilePaths; //保存文件的絕對(duì)路徑
FString ExtensionStr = TEXT("*.*"); //文件類型
const FString ProjectDirPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()); //獲取工程目錄的絕對(duì)路徑
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
DesktopPlatform->OpenFileDialog(nullptr, TEXT("文件"), FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()), TEXT(""), *ExtensionStr, EFileDialogFlags::None, JsonFilePaths);
//判斷文件是否存在
if ( !FPlatformFileManager::Get().GetPlatformFile().FileExists(*JsonFilePaths[0]) )
{
UE_LOG( LogTemp, Warning, TEXT("%s not exist"), *JsonFilePaths[0] );
return;
}
//1.2 根據(jù)文件路徑讀取文件內(nèi)存,保存到FString變量中
FString JsonStr;
FFileHelper::LoadFileToString(JsonStr, *(JsonFilePaths[0]));
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//2.將 JsonStr 變量存儲(chǔ)到一個(gè) FJsonObject 變量中
TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonStr); //創(chuàng)建一個(gè)Json 閱讀器
TSharedPtr<FJsonObject> JsonObject; //創(chuàng)建一個(gè)Json對(duì)象
FJsonSerializer::Deserialize(JsonReader, JsonObject); //反序列化,將JsonReader里面的數(shù)據(jù),傳到JsonObject中
//-----------------------------------------------------------------------------------------------------------------
//3.讀取Json對(duì)象中的數(shù)據(jù)(例如,讀取Game對(duì)應(yīng)的數(shù)據(jù)值)
FString sGameValue = JsonObject->GetStringField("Game");
UE_LOG(LogTemp, Warning, TEXT("Game Value: %s"), *sGameValue);
return;
}
藍(lán)圖中驗(yàn)證功能
- 在關(guān)卡藍(lán)圖中寫如下代碼
![]()
- 日志文件輸出結(jié)果如圖:結(jié)果正確打印出來。
![]()
2.3.2 WriteJSONFile函數(shù)實(shí)現(xiàn)
大致思路
- 準(zhǔn)備工作:新建一個(gè)結(jié)構(gòu)體用于存放數(shù)據(jù)
- 開始寫入:單個(gè)數(shù)據(jù)寫入、數(shù)組數(shù)據(jù)寫入
- 驗(yàn)證結(jié)果:打印出存儲(chǔ)Json內(nèi)容的字符串
// 存放數(shù)據(jù)的結(jié)構(gòu)體
struct Info {
FString name;
int32 health;
};
void UJSONFileReadWrite::WriteJSONFile()
{
//-----------------------------------------------------------------------------------------------------------------
//1. 準(zhǔn)備階段
//1.1 聲明存儲(chǔ)寫入的Json內(nèi)容的字符串
FString JsonStr;
//1.2創(chuàng)建一個(gè)Json編寫器
TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&JsonStr);
//-----------------------------------------------------------------------------------------------------------------
//2. 寫入單個(gè)數(shù)據(jù)
JsonWriter->WriteObjectStart(); //開始 一個(gè)Json對(duì)象的寫入(一個(gè)Json對(duì)象對(duì)應(yīng)一個(gè){}中的內(nèi)容)
JsonWriter->WriteValue(TEXT("Time"), TEXT("1998")); //寫入 一個(gè)鍵值對(duì)("Time" : "1998")
JsonWriter->WriteValue(TEXT("age"), TEXT("27")); //寫入 一個(gè)鍵值對(duì)("age" : "27")
JsonWriter->WriteObjectEnd(); //結(jié)束 一個(gè)Json對(duì)象的寫入
//2.1 寫入數(shù)組數(shù)據(jù)
TArray<Info> Players; //存放數(shù)組數(shù)據(jù)的變量
struct Info info;
info.name = TEXT("player1"); info.health = 30; Players.Add(info);
info.name = TEXT("player2"); info.health = 200; Players.Add(info);
info.name = TEXT("player3"); info.health = 999; Players.Add(info);
//JsonWriter->WriteArrayStart(L"players"); ???為什么調(diào)用WriteArrayStart函數(shù)帶參數(shù)就會(huì)報(bào)錯(cuò):數(shù)組越界
JsonWriter->WriteArrayStart();
for (Info player : Players)
{
JsonWriter->WriteObjectStart();
JsonWriter->WriteValue(L"name", player.name);
JsonWriter->WriteValue(L"health", player.health);
JsonWriter->WriteObjectEnd();
}
JsonWriter->WriteArrayEnd();
//-----------------------------------------------------------------------------------------------------------------
//3. 停止寫入操作
JsonWriter->Close();
//4. 打印結(jié)果
UE_LOG(LogTemp, Warning, TEXT("JsonStr Value: %s"), *JsonStr);
return;
}
LOG輸出結(jié)果:
文章來源:http://www.zghlxwxcb.cn/news/detail-771004.html
2.3.3 疑惑
為什么調(diào)用WriteArrayStart函數(shù)時(shí)帶參數(shù)就會(huì)報(bào)錯(cuò):數(shù)組越界。我看別的博主都是帶參數(shù)調(diào)用都沒有問題。異常內(nèi)容如下,望各位大佬指點(diǎn)。
文章來源地址http://www.zghlxwxcb.cn/news/detail-771004.html
到了這里,關(guān)于【程序員必備】UE4 C++ 虛幻引擎:詳解JSON文件讀、寫、解析,打造高效開發(fā)!的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!