【程序员必备】UE4 C++ 虚幻引擎:详解JSON文件读、写、解析,打造高效开发!


请添加图片描述

  • 🙋‍♂️ 作者:海码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函数实现

大致思路

  1. 读取磁盘中的 JSON 文件,使用 FFileHelper::LoadFileToString 函数将文件内容读取到FString类型的变量中;
  2. 将 FString 变量存储到一个 FJsonObject 变量中;
  3. 读取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文件绝对路径
	TArray<FString>		JsonFilePaths;																//保存文件的绝对路径
	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<TJsonReader<>>	JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonStr);	//创建一个Json 阅读器
	TSharedPtr<FJsonObject>		JsonObject;													//创建一个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函数实现

大致思路

  1. 准备工作:新建一个结构体用于存放数据
  2. 开始写入:单个数据写入、数组数据写入
  3. 验证结果:打印出存储Json内容的字符串
// 存放数据的结构体
struct Info {
	FString name;
	int32 health;
};

void UJSONFileReadWrite::WriteJSONFile()
{
	//-----------------------------------------------------------------------------------------------------------------
	//1. 准备阶段
	//1.1 声明存储写入的Json内容的字符串
	FString JsonStr;
	//1.2创建一个Json编写器
	TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::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<Info> 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函数时带参数就会报错:数组越界。我看别的博主都是带参数调用都没有问题。异常内容如下,望各位大佬指点。
在这里插入图片描述

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值