UE4 JSON构造和解析

目录

  • JSON简介
  • 构造Json格式
    • 方法一:使用JsonObject
      • 添加JSON头文件
      • 构造Json Object
      • 序列化
      • 完整代码
    • 方法二:使用JsonWriter
      • 完整代码
  • 解析Json格式
    • 使用JsonObject
      • 完整代码
  • 参考链接

JSON简介

JSON是一个轻量级的独立于编程语言的数据交换格式,它既便于人类读写,又适合机器读写。

JSON中的基本定义:

  • JSON Object: { }内的name-value对的集合。特点是无序、不同类型
  • JSON Array: [ ]内value的有序集合。特点是有序、相同类型
  • JSON value: object/array/string/number/“true”/“false”/“null”

参考链接:link

构造Json格式

本文的目标是用UE4构造以下Json格式,包含字符串、数字、数组和结构体:

{
	"Name": "Mei",
	"Age": 18,
	"Friends": 
	[
		"Yi",
		"Tao",
		"Qing"
	],
	"Dog":
	{
		"Name": "Ben",
		"Age": 5
	}
}

UE4中可以使用两种方法构造Json格式。

方法一:使用JsonObject

添加JSON头文件

在Project.Build.cs文件中的PrivateDependencyModuleNames添加Source/Runtime目录下的Json模块,然后在项目文件中包含以下头文件:

#include "Json/Public/JSON.h"
#include "Json/Public/Serialization/JsonSerializer.h"
#include "Json/Public/Serialization/JsonReader.h"

注:本文UE4版本为4.26

构造Json Object

在UE4中,Json Object使用的是FJsonObject类,这个类维护了一个name-value对的map和相应的操作。以下是构造一个FJsonObject类,Root是指向它的指针:

TSharedPtr<FJsonObject> Root = MakeShareable(new FJsonObject); //TsharedRef对应C++11智能指针

一旦创建Json对象的root,你们就可以添加你们想要的name-value对。下面,我们就来为Json对象添加一些属性:

//创建Json Object
TSharedPtr<FJsonObject> Root = MakeShareable(new FJsonObject); //TsharedRef对应C++11智能指针

//构造数组
TArray<TSharedPtr<FJsonValue>> myFriends;
TSharedPtr<FJsonValueString> a = MakeShareable(new FJsonValueString("Yi"));
myFriends.Add(a);
TSharedPtr<FJsonValueString> b = MakeShareable(new FJsonValueString("Tao"));
myFriends.Add(b);
TSharedPtr<FJsonValueString> c = MakeShareable(new FJsonValueString("Qing"));
myFriends.Add(c);

//构造结构体
TSharedPtr<FJsonObject> myDog = MakeShareable(new FJsonObject);
myDog->SetStringField("Name", "Ben");
myDog->SetNumberField("Age", 5);

//添加属性
Root->SetStringField("Name", "Mei");
Root->SetNumberField("Age", 18);
Root->SetArrayField("Friends", myFriends);
Root->SetObjectField("Dog", myDog);

序列化

一旦你构建完成FJsonObject,接下来你就会想如何拿到它的字符串表现形式。你可以使用TJsonWriterFactory来写Json,并利用FJsonSerializer来序列化JsonObject对象。

//序列化
FString OutputString;
TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> Writer = 	TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&OutputString);
FJsonSerializer::Serialize(Root.ToSharedRef(), Writer); //Serialize:把内存中的对象转为便于存储和传输的数据

上面代码会将Json对象输出到OutputString中去。接着,你就能拿OutputString来做你想做的事情,例如发送Http请求,或者存储到文件/数据库中。

注:TJsonWriterFactory是一个接受policy的模版,用于决定Json是如何被打印的。例如,"pretty"模式(易读的格式化),或者"condensed"模式(空白符都被去除掉)。他们对应的名字就是TCondensedJsonPrintPolicy和TPrettyJsonPrintPolicy。

完整代码

	//创建Json Object
	TSharedPtr<FJsonObject> Root = MakeShareable(new FJsonObject); //TsharedRef对应C++11智能指针

	//构造数组
	TArray<TSharedPtr<FJsonValue>> myFriends;
	TSharedPtr<FJsonValueString> a = MakeShareable(new FJsonValueString("Yi"));
	myFriends.Add(a);
	TSharedPtr<FJsonValueString> b = MakeShareable(new FJsonValueString("Tao"));
	myFriends.Add(b);
	TSharedPtr<FJsonValueString> c = MakeShareable(new FJsonValueString("Qing"));
	myFriends.Add(c);
	
	//构造结构体
	TSharedPtr<FJsonObject> myDog = MakeShareable(new FJsonObject);
	myDog->SetStringField("Name", "Ben");
	myDog->SetNumberField("Age", 5);

	//添加属性
	Root->SetStringField("Name", "Mei");
	Root->SetNumberField("Age", 18);
	Root->SetArrayField("Friends", myFriends);
	Root->SetObjectField("Dog", myDog);

	//序列化和创建Json Writer
	FString OutputString;
	TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> Writer = 	TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&OutputString);
	FJsonSerializer::Serialize(Root.ToSharedRef(), Writer); //Serialize:把内存中的对象转为便于存储和传输的数据

	//打印
	UE_LOG(LogNet, Warning, TEXT("output 1:\n%s"), *OutputString);

方法二:使用JsonWriter

不用JsonObject,只用JsonWriter来构造Json。

完整代码

struct FDog
{
	FString name;
	int32 age;
};
struct FDog myDog;
myDog.name = "Ben";
myDog.age = 5;
TArray<FString> myFriends;
myFriends.Add("Tao");
myFriends.Add("Yi");
myFriends.Add("Qing");

//创建Json Writer
FString OutputString;
TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> Writer = TJsonWriterFactory< TCHAR, TPrettyJsonPrintPolicy<TCHAR> >::Create(&OutputString);

Writer->WriteObjectStart(); //最外层   

Writer->WriteValue("Name", TEXT("Mei")); //写字符串
Writer->WriteValue("Age", 18); //写数字

Writer->WriteArrayStart("Friends"); //写数组
for (int32 i = 0; i < myFriends.Num(); ++i)
{
	Writer->WriteValue(myFriends[i]);
}
Writer->WriteArrayEnd();

Writer->WriteObjectStart("Dog"); //写结构体
Writer->WriteValue("Name", TEXT("Ben"));
Writer->WriteValue("Age", 5);
Writer->WriteObjectEnd();

Writer->WriteObjectEnd();
Writer->Close();

//打印
UE_LOG(LogNet, Warning, TEXT("output 2:\n%s"), *OutputString);

解析Json格式

使用JsonObject

下面我们接着来演示如何将上面的Json字符串内容还原成Json对象。首先我们需要一个FJsonObject对象:

TSharedPtr<FJsonObject> JsonObject;

在前面我们使用TJsonWriter和TJsonWriterFactory来序列化Json对象,现在我们需要使用TJsonReader和TJsonReaderFactory来反序列化:

TSharedRef<TJsonReader> Reader = TJsonReaderFactory<>::Create(JsonString);

其中JsonString就是我们要反序列化的Json字符串内容。

下一步,我们就来反序列化Json,使用Derialize函数。

FJsonSerializer::Deserialize(Reader, JsonObject);

反序列化结束后,我们就可以从JsonObject中读取数据:

JsonObject->GetStringField(TEXT("Name")); //将返回"Mei"

完整代码

解析Json格式举例

FString JsonString = TEXT("{\"Name\":\"Mei\",\"Age\":18,\"Friends\":[\"Tao\",\"Yi\",\"Qing\"],\"Dog\":{\"Name\":\"Ben\",\"Age\":5}}");
FString name;
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString); //JsonString是要解析的字符串
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
	name = JsonObject->GetStringField(TEXT("Name")); //将返回"Mei"
	//其它JSon类型的解析和字符串类似
}

//打印
UE_LOG(LogNet, Warning, TEXT("ReadJson output:\n%s"), *name);

解析数字、数组、结构体可对应使用GetNumberField, GetArrayField, GetObjectField。更多函数在Engine/Source/Runtime/Json/Private/Dom/JsonObject.cpp中。

以上代码运行结果:

参考链接

UE4 Json读写:
https://zhuanlan.zhihu.com/p/69710088
https://blog.csdn.net/qq_31930499/article/details/88366530
智能指针:
https://www.cnblogs.com/WindSun/p/11444429.html

你可能感兴趣的:(json,unreal)