一.介绍
Json是一种数据对象,数据由键值对组成.
1.简单的Json数据对象:
//{"键1":"值1","键2":"值2",....}
{"Name":"Tom","Age":"18","Sex":"man"}
2.Json对象作为键值对的值
//班长信息:Json对象作为值
{"MonitorInfo":{"Name":"Tom","Age":"20","Sex":"man"}}
3.Json对象数组
[
//第一个对象
{"Name":"Tom","Age":"18","Sex":"man"},
//第二个对象
{"Name":"Jerry","Age":"17","Sex":"man"},
//第三个对象
{"Name":"Lily","Age":"20","Sex":"woman"}
]
4.Json对象数组作为键值对的值
{
//一班
"ClassNum":"1",
//老师叫张三
"TeacherName":"ZhangSan",
//学生数组
"Students":
[
//学生1
{"Name":"Tom","Age":"18","Sex":"man"},
//学生2
{"Name":"Jerry","Age":"17","Sex":"man"},
//学生3
{"Name":"Lily","Age":"20","Sex":"woman"}
]
}
二.UE4 Json使用说明
使用Json模块需要在Build.cs中将Json模块导入
PublicDependencyModuleNames.AddRange(
new string[]
{
"Json"
}
);
1.FJsonObject说明
FJsonObject 在UE4里表示一个Json对象,用于存储Json数据
(1).初始化方式
/**因为FJsonObject并非UObject的派生类,无法自动进行垃圾回收,所以使用共享指针防止内存泄漏
*下面定义一个空的Json对象
*/
TSharedPtr<FJsonObject> Object;
(2)FJsonObject存储数据的几种形式
①.将常规类型作为值存储
//1.存储数据节点
//(1)SetStringField(FString key,FString value) 存储一个FString字段
Object->SetStringField(TEXT("Name"),TEXT("Tom"));
/**
*(2)SetNumberField(FString key,double value) 存储一个浮点型字段
*ps:并没有SetIntegerField,存储整形也可以使用这个
*/
Object->SetNumberField(TEXT("Age"),18);
//(3)SetBoolField(FString key,bool value) 存储一个bool型字段
Object->SetBoolField(TEXT("IsMan"),true);
//截止到次,Object内的数据为{"Name":"Tom","Age":18,"IsMan":true}
实机测试代码
②.将FJsonObject作为值存储
//创建一个JsonObject
TSharedPtr<FJsonObject>Object= MakeShareable(new FJsonObject);
//填充字段信息
Object->SetStringField(TEXT("Name"), TEXT("Tom"));
Object->SetNumberField(TEXT("Age"), 18);
Object->SetBoolField(TEXT("IsMan"), true);
//创建另一个JsonObject作为上面的JsonObject中的一个字段的值
TSharedPtr<FJsonObject>obj = MakeShareable(new FJsonObject);
obj->SetNumberField(TEXT("weight"), 130);
obj->SetNumberField(TEXT("height"), 180);
obj->SetStringField(TEXT("Hobby"), TEXT("Game"));
//将obj作为Object中的Info字段的值
Object->SetObjectField(TEXT("Info"), obj);
实机测试代码
③.将TArray<TSharedPtr<FJsonValue>>作为值存储//结构大致如下
{
"field1":"xx",
"field2":"yy",
"fields":
[
//切记!数组中的元素必须要是字段都一致的Json对象,所有字段名都得是一样
{"Name":"tom","Age":18},
{"Name":"jerry","Age":17}
]
}
/**
*SetArrayField(FString key,TArray>value)
*存储一个数组作为某个字段的值
*/
//1.创建一个空的FJsonValue数组
TArray<TSharedPtr<FJsonValue>>JsonValueArray;
//2.创建两个FJsonObject作为数组元素
TSharedPtr<FJsonObject>vobj1=MakeShareable(new FJsonObject);
vobj1->SetStringField(TEXT("familymember"),TEXT("Jerry"));
TSharedPtrv<FJsonObject>obj2=MakeShareable(new FJsonObject);
vobj2->SetStringField(TEXT("familymember"),TEXT("John"));
//3.将两个FJsonObject转化为FJsonValue,存储到数组中,到此数组填充完毕
JsonValueArray.Add(MakeShareable(new FJsonValueObject(vobj1)));
JsonValueArray.Add(MakeShareable(new FJsonValueObject(vobj2)));
Object->SetArrayField(TEXT("Famliy"),JsonValueArray);
/**
*截止到此 Object内的信息
*{
* "Name":"Tom",
* "Age":18,
* "IsMan";true,
* "Family":
* [
* {"familymember":"Jerry"},
* {"familymember":"john"}
* ]
*}
*SetArrayField要比其他的用法稍稍复杂一些,注意理解
*/
实机测试代码
(3)FJsonObject获取数据的方式
①.判断是否拥有某个字段
判断传入的字段是否存在,在你想要查询某个字段的数据但是不确定Json中是否有这个字段时,可以先判断一下
进阶查询用法,不光可以判断字段是否存在,还能判断字段的类型是否一致
②TryGetXXField
/**
*FieldName:要查询的字段名
*OutValue:该参数需要传入一个引用,用于接收查询到的结果
*返回一个bool值,查询到数据返回true,查询不到返回false
*/
TryeGetXXField(FString FieldName,XXType& OutValue);
//假设一个简单的json对象(伪代码)
TSharedPtr<FJsonObject>obj={"Name":"Tom","Age":18,"IsMan":true};
FString OutString;
obj->TryGetStringField("Name",OutString); //OutString=Tom;
bool bIsMan=false;
obj->TryGetBoolField("IsMan",bIsMan); //bIsMan=true;
int32 age=0;
//TryGetNumberField可以支持获取double int32 uint32 int64 类型的数值
obj->TryGetNumberField("Age",age); //age=18;
//obj还能够获得FJsonObject和TArray<FJsonValue>数组
③GetXXField
GetNumberField(获取浮点型数值) return double,
GetBoolField(获取bool型数值) return bool ,
GetArrayField(获取FJsonValue数组作为数值) return TArray<TSharedPtr<FJsonValue>>,
GetObjectField(获取FJsonObject作为数值) return TSharedPtr<FJsonObject>.
说明:
使用TryGet和Get都可以用来获取数据,如果Json数据的字段是明确的,那么可以直接使用Get来获取.如果不确定,可以使用TryGet,根据需求选择即可
(4)逆序列化(Deserialize)FJsonObject
常用于将一个FString类型的Json数据存入到FJsonObject中
/**
*JsonStr是UE4中的Json数据
*注意!!! 在UE4中需要使用\"(反斜杠+双引号,转义字符) 来替代"(双引号)
*看到 \" 直接在心里替换成 " 即可
*/
FString JsonStr=TEXT("{\"Name\":\"Tom\",\"Age\":\"18\",\"Sex\":\"man\"}");
//使用工厂类,把FString格式的Json数据存到创建出来的Json Reader中
TSharedRef<TJsonReader<>>Reader = TJsonReaderFactory<>::Create(JsonStr);
//创建一个空的JsonObject(Json对象,因为其基类不是UObject,为了防止内存泄漏,使用共享指针)
TSharedPtr<FJsonObject>Object;
//FJsonSerializer 通过Deserialize(逆序列化)拿Reader中存储的数据来填充空的Json对象
FJsonSerializer::Deserialize(Reader,Object);
//如果逆序列化成功,Json对象IsValid将返回true,然后我们就可以通过他读取数据了
if(Object.IsValid())
{
//Json对象通过GetStringField,传入字段名(键),获得字符串类型的值
FString Name=Object->GetStringField(TEXT("Name"));
//Json对象通过GetIntegerField,传入字段名(键),获得整形的值
int32 Age=Object->GetIntegerField(TEXT("Age"));
}
实机测试代码
(5)序列化(Serialize)FJsonObject
常用于将FJsonObject中的数据写入到FString中
//准备一个用于序列化的FJsonObject
TSharedPtr<FJsonObject>Obj = MakeShareable(new FJsonObject);
Obj->SetStringField("Name", "Tom");
Obj->SetNumberField("Age",18);
Obj->SetBoolField("IsMan", true);
//创建一个空的FString用于接收序列化后的json数据
FString OutString;
TSharedRef<TJsonWriter< TCHAR, TCondensedJsonPrintPolicy<TCHAR>>>Writer = TJsonWriterFactory< TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&OutString);
//Serializer将Json对象中的数据通过Writer写入到outstring中
bool bResult=FJsonSerializer::Serialize(Obj.ToSharedRef(),Writer);
if (bResult)
{
UE_LOG(LogTemp, Warning, TEXT("serialize succeeded!! outstring:%s"), *OutString);
}
可以看到空的字符串被写入了数据
2.FJsonValue说明
FJsonValue在UE4中作为Json数据键值对中的值存在
(1).初始化方式
FJsonValue针对每一种Json值类型都进行了派生,引擎不提倡我们直接使用FJsonValue基类,而是提倡我们根据值类型来选择不同的派生类
派生类如下
1.FJsonValueString
//初始化方式
TSharedPtr<FJsonValue>StrVal = MakeShareable(new FJsonValueString(""));
2.FJsonValueNumber
//初始化方式
TSharedPtr<FJsonValue>numVal = MakeShareable(new FJsonValueNumber(""));
3.FJsonValueBoolean
//初始化方式
TSharedPtr<FJsonValue>boolVal = MakeShareable(new FJsonValueBoolean(false));
4.FJsonValueObject
//初始化方式
TSharedPtr<FJsonObject>Obj = MakeShareable(new FJsonObject);
TSharedPtr<FJsonValue>ObjVal = MakeShareable(new FJsonValueObject(Obj));
5.FJsonValueArray
//初始化方式
TArray<TSharedPtr<FJsonValue>>InArray;
TSharedPtr<FJsonValue>ArrayVal = MakeShareable(new FJsonValueArray(InArray));
还有一些不太常用的派生类,想了解更多可以去Engine\Source\Runtime\Json\Public\Dom\JsonValue.h 中进行查看
(2)常用节点
①.AsXXX
根据选择的类型(FJsonValueXXX),可以使用对应的AsXXX来获取数据内容
比如FJsonValueString 可以使用AsString返回存储的字符串
②.TryGetXXX
与AsXXX一样,根据类型来决定使用具体的TryGet节点获取数据
3.示例代码
//创建主体Json对象
TSharedPtr<FJsonObject>TomObj = MakeShareable(new FJsonObject);
//填充常规类型字段数据
TomObj->SetStringField("Name", "Tom");
TomObj->SetNumberField("Age",18);
TomObj->SetBoolField("IsMan", true);
//创建一个子Json对象作为值
TSharedPtr<FJsonObject>InfoObj = MakeShareable(new FJsonObject);
InfoObj->SetNumberField("Height", 180);
InfoObj->SetNumberField("Weight", 70);
TomObj->SetObjectField("Info", InfoObj);
//创建两个子Json对象,数组的元素
TArray<TSharedPtr<FJsonValue>>ValueArray;
TSharedPtr<FJsonObject>FriendObj1= MakeShareable(new FJsonObject);
TSharedPtr<FJsonObject>FriendObj2 = MakeShareable(new FJsonObject);
//填充子对象数据
FriendObj1->SetStringField("Name", "jerry");
FriendObj1->SetNumberField("IsMan", true);
FriendObj2->SetStringField("Name", "lily");
FriendObj2->SetNumberField("IsMan", false);
ValueArray.Add(MakeShareable(new FJsonValueObject(FriendObj1)));
ValueArray.Add(MakeShareable(new FJsonValueObject(FriendObj2)));
TomObj->SetArrayField("Friends", ValueArray);
FString OutString;
TSharedRef<TJsonWriter< TCHAR, TCondensedJsonPrintPolicy<TCHAR>>>Writer = TJsonWriterFactory< TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&OutString);
bool bResult=FJsonSerializer::Serialize(TomObj.ToSharedRef(),Writer);
if (bResult)
{
UE_LOG(LogTemp, Warning, TEXT("serialize succeeded!! outstring:%s"), *OutString);
}
作者:埃罗芒阿Sensal
https://www.bilibili.com/read/cv10071665/
出处: bilibili