目录
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