有别于常见的UE
中处理Json
的方式,灵感来源于GameplayTag
和 UE JsonObject
中存储键值的方式:TMap<FString, TSharedPtr<FJsonValue>> Values;
UE中常见的解决方案:
VaRest Plugin
:在蓝图中将Json
字符串转成JsonObject
,然后就是ToValue
ToObject
HasFiled
等繁琐的操作- 优点:执行效率高
- 缺点:遇到多层次嵌套的
JsonObject
,你将在蓝图中亲手织出一个盘丝洞
JsonToStruct
:这种方案,就是用C++
或蓝图,创建一个和Json
完全一致的结构,甚至大小写也有影响数据解析的正确性- 优点:方案优雅,效率高,易维护
- 缺点:遇到复杂的
Json
结构,需要创建N多个不同的结构体,也不是很方便
于是,我就在想,有没有一种可能,牺牲一些什么,换来一些什么?
恰好最近一直在学习UE GAS
部分的内容,感受到GameplayTag
作为逻辑的条件判断,非常的优雅和灵活,所以就模仿使用GameplayTag
的方式,写了这个插件
优点:
- 通过类型
GameplayTag
的方式,定位到Json
中值 - 不用在蓝图中织网了
- 减少专门创建一堆结构体去
JsonToStruct
缺点:
- 也就内存占用大了一点点
- 也就消耗大了那么一点点
纯粹写着玩的!!!
- 利用
UE Json
库,将Json
字符串,依照Json
中的键值,一对对的解析到TMap
中 - 遇到值为
JsonObject
,就迭代解析
遗憾:
- 考虑到复杂庞大的
Json
结构中,可能存在很多层的数组嵌套,所以我的选择是遇到值为Array
,就将整个Array
作为字符串作为解析值 - 如果需要解析数组的内容,需要单独使用另一个蓝图节点
- 如果数组内的元素是:
int, float, int, string
就可以直接得到数组内的值object, array
则不会迭代解析,直接将整个元素作为字符串存在StringArray
- 总之,通过组合使用
ReadJson_Async
,GetNodeData
和ParseJsonArray
这两个节点,就可以解析整个Json
中的任意内容
注意:
-
Json
数组内的元素必须一致 -
不能出现这种情况:
[1, 2.2, "123", {key: value}, [1, 2, 3]]
-
这种的就没法使用这两个通用节点去解析了,只能自行处理了
ReadJson_Async
:
- 解析
Json
,将里面的键值对按照路径进行迭代,存入ParsedData
中 - 实际使用时,建议将
ParsedData
存入变量中
GetNodeData
:
-
NodePath
就是你需要的键值所在的路径{ "1": { "2":"123" } }
-
GetNodePath("1.2")
就可以得到NodeData
{ "Key":"2", "Value": { "StringValue":, // 这里可以获得 123 "BoolValue":, "IntValue":, "FloatValue": } }
ParseJsonArray
:
-
用于解析由
Array
转成的字符串,如果数组元素是:Array
,Object
,则会将它们转成字符串存入StringArray
-
例如:传入字符串到
ParseJsonArray
[ {"name": "Google", "url": "www.google.com"}, {"name": "Runoob", "url": "www.runoob.com"}, {"name": "Taobao", "url": "www.taobao.com"} ]
-
得到结构体
ArrayValue
{ "StringArray":, // 如果带解析的数组内元素是:String, Array, Object,结果都在这里 "BoolArray", "IntArray", "FloatArray" }
考虑到数组元素是:Array
, Object
,则会将它们转成字符串存入StringArray
;
如果需要进一步解析:按照数组内元素的类型,重复使用下来的节点
Array
使用ParseJsonArray
Object
使用ReadJson_Async
测试 Json
{
"name": "网站",
"num": 3,
"sites":
[
{"name": "Google", "url": "www.google.com"},
{"name": "Runoob", "url": "www.runoob.com"},
{"name": "Taobao", "url": "www.taobao.com"}
],
"testBool": true
}
{
"array":
{
"int": [1, 2, 3],
"string": ["a", "b", "c"],
"bool": [true, false, true],
"float": [1.1, 2.2, 3.3],
"double": [1.1, 2.2, 3.3],
"object": [{"name": "a"}, {"name": "b"}, {"name": "c"}],
"array": [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}
}
{
"1":
{
"2":
{
"3":
{
"4": "123456789"
}
}
}
}
如果明确直到对应的Node Value
的类型,可以直接使用这个系列的蓝图节点,比GetNodeData
更简洁
测试Json1
:
{
"array":
{
"int": [1, 2, 3],
"string": ["a", "b", "c"],
"bool": [true, false, true],
"float": [1.1, 2.2, 3.3],
"double": [1.1, 2.2, 3.3],
"object": [{"name": "a"}, {"name": "b"}, {"name": "c"}],
"array": [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}
}
如果明确知道,对应的Node Value
的值是Array
,可以直接用这个蓝图节点,更便捷;
注意:如果Array
的元素是Object
,会将Object
解析成String
,如果需要进一步解析,使用:ReadJson_Async
就是将 GetNodeValue_ToString
和ParseJsonArray_To[]Array
节点结合使用;
例如想要得到Json2
中的array.object
,直接使用GetNodeValue_ToStringArray
,就可以直接得到 TArray<FString>
;
其它依次类推