目录

0 应用场景1 功能前瞻1.1JSON格式介绍

2 功能实现2.1 准备工作2.2 注意事项2.3 具体功能实现2.3.1 ReadJSONFileByFN函数实现2.3.2 WriteJSONFile函数实现2.3.3 疑惑

‍♂️ 作者:海码007 专栏:UE虚幻引擎专栏 标题:【程序员必备】UE4 C++ 虚幻引擎:详解JSON文件读、写、解析,打造高效开发!❣️ 寄语:人生的意义或许可以发挥自己全部的潜力,所以加油吧! 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正

0 应用场景

在游戏开发中,Json 文件常被用来保存游戏数据或配置参数,如把游戏对象的内部状态存储到磁盘文件,即序列化游戏对象的时候,或在文件中配置一些游戏相关的参数时。本文将详细讲解如何在 UE 中读取与解析 Json 文件。

1 功能前瞻

创建一个 JSONFileReadWrite 类,两个成员函数 ReadJSONFileByFN、WriteJSONFile。功能分别是读取一个 JSON 格式的文件,并可以解析其中数据;另一个功能是写入一个 JSON 文件。

1.1JSON格式介绍

{

"Game": "LOL",

"Year": 2023,

"Judge":

{

"name": "Uzi",

"age": 26,

},

"Player": [

{

"name": "xiaoming",

"levels": 22

},

{

"name": "xiaohu",

"levels": 23

}

]

}

普通类型的值:Json数据格式就是一种嵌套的关系,花括号里面其实就是保存了一个个键值对(学过C++map容器应该很好理解)例如,Game和Year就是Key键,“LOL”、2023就是对应的值,只不过一个是字符串类型,一个是整数类型。

"Game": "LOL",

"Year": 2023,

Json对象类型的值:当然也可以是一个Json对象类型,如下Judge的值就是一个花括号包裹住的类型,也就是一个Json对象。

"Judge":

{

"name": "Uzi",

"age": 26,

},

数组类型的值:如下所示,Player的值是由 [ ] 包围住,其中数组是Json对象类型

"Player": [

{

"name": "xiaoming",

"levels": 22

},

{

"name": "xiaohu",

"levels": 23

}

]

2 功能实现

在了解Json数据的基本格式后,就可以对其进行读写操作。

2.1 准备工作

创建一个UE C++工程,并新建一个JSONFileReadWrite类继承UObject类,创建两个函数,并且让这个C++类和成员函数可以被蓝图调用(加入说明符即可)。

// 类是使用BlueprintType将其暴露给蓝图使用

UCLASS(BlueprintType)

class CPP_API UJSONFileReadWrite : public UObject

{

GENERATED_BODY()

public:

// 函数是使用BlueprintCallable将其暴露给蓝图使用

UFUNCTION(BlueprintCallable)

void ReadJSONFileByFN();

UFUNCTION(BlueprintCallable)

void WriteJSONFile();

};

2.2 注意事项

使用UE的Json功能时,需要在build.cs文件中添加Json模块依赖,不然编译不通过。

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Json" });

2.3 具体功能实现

2.3.1 ReadJSONFileByFN函数实现

大致思路

读取磁盘中的 JSON 文件,使用 FFileHelper::LoadFileToString 函数将文件内容读取到FString类型的变量中;将 FString 变量存储到一个 FJsonObject 变量中;读取FJsonObject 对象中的数据;

【提示】使用文件选择对话框需要下面两个头文件

#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文件绝对路径

TArrayJsonFilePaths; //保存文件的绝对路径

FString ExtensionStr = TEXT("*.*"); //文件类型

const FString ProjectDirPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()); //获取工程目录的绝对路径

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 根据文件路径读取文件内存,保存到FString变量中

FString JsonStr;

FFileHelper::LoadFileToString(JsonStr, *(JsonFilePaths[0]));

//-----------------------------------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------------------------------------

//2.将 JsonStr 变量存储到一个 FJsonObject 变量中

TSharedRef>JsonReader = TJsonReaderFactory::Create(JsonStr); //创建一个Json 阅读器

TSharedPtrJsonObject; //创建一个Json对象

FJsonSerializer::Deserialize(JsonReader, JsonObject); //反序列化,将JsonReader里面的数据,传到JsonObject中

//-----------------------------------------------------------------------------------------------------------------

//3.读取Json对象中的数据(例如,读取Game对应的数据值)

FString sGameValue = JsonObject->GetStringField("Game");

UE_LOG(LogTemp, Warning, TEXT("Game Value: %s"), *sGameValue);

return;

}

蓝图中验证功能

在关卡蓝图中写如下代码日志文件输出结果如图:结果正确打印出来。

2.3.2 WriteJSONFile函数实现

大致思路

准备工作:新建一个结构体用于存放数据开始写入:单个数据写入、数组数据写入验证结果:打印出存储Json内容的字符串

// 存放数据的结构体

struct Info {

FString name;

int32 health;

};

void UJSONFileReadWrite::WriteJSONFile()

{

//-----------------------------------------------------------------------------------------------------------------

//1. 准备阶段

//1.1 声明存储写入的Json内容的字符串

FString JsonStr;

//1.2创建一个Json编写器

TSharedRef>> JsonWriter = TJsonWriterFactory>::Create(&JsonStr);

//-----------------------------------------------------------------------------------------------------------------

//2. 写入单个数据

JsonWriter->WriteObjectStart(); //开始 一个Json对象的写入(一个Json对象对应一个{}中的内容)

JsonWriter->WriteValue(TEXT("Time"), TEXT("1998")); //写入 一个键值对("Time" : "1998")

JsonWriter->WriteValue(TEXT("age"), TEXT("27")); //写入 一个键值对("age" : "27")

JsonWriter->WriteObjectEnd(); //结束 一个Json对象的写入

//2.1 写入数组数据

TArray Players; //存放数组数据的变量

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"); ???为什么调用WriteArrayStart函数带参数就会报错:数组越界

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. 打印结果

UE_LOG(LogTemp, Warning, TEXT("JsonStr Value: %s"), *JsonStr);

return;

}

LOG输出结果:

2.3.3 疑惑

为什么调用WriteArrayStart函数时带参数就会报错:数组越界。我看别的博主都是带参数调用都没有问题。异常内容如下,望各位大佬指点。

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: