UE4 虚幻引擎写入json

一.介绍

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值