有别于常见的UE中处理Json的方式,灵感来源于GameplayTag 和UE JsonObject中存储键值的方式:TMap<FString, TSharedPtr<FJsonValue>> Values;
UE中常见的解决方案:
VaRest Plugin:在蓝图中将Json字符串转成JsonObject,然后就是ToValueToObjectHasFiled等繁琐的操作优点:执行效率高 缺点:遇到多层次嵌套的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中的任意内容 注意:
ReadJson_Async:
解析Json,将里面的键值对按照路径进行迭代,存入ParsedData中 实际使用时,建议将ParsedData存入变量中 GetNodeData:
ParseJsonArray:
考虑到数组元素是:Array,Object ,则会将它们转成字符串存入StringArray;
如果需要进一步解析:按照数组内元素的类型,重复使用下来的节点
Array使用ParseJsonArrayObject使用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" } } }}
3.1 GetNodeValue_To [ String, Int, Float, Bool ] 如果明确直到对应的Node Value的类型,可以直接使用这个系列的蓝图节点,比GetNodeData更简洁
3.2 ParseJsonArray_To [String, Int, Float, Bool] Array 测试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
3.3 GetNodeValue_To [String, Int, Float, Bool] Array 就是将GetNodeValue_ToString和ParseJsonArray_To[]Array节点结合使用;
例如想要得到Json2中的array.object,直接使用GetNodeValue_ToStringArray,就可以直接得到TArray<FString>;
其它依次类推
用于解析较小的Json,使用起来比ReadJson_Async简单快捷
打印新携带调用所在的蓝图名称,方便定位所在蓝图
集合[读取,解析]一体,面向非大型Json,一次性使用 (不推荐重复性调用,更不推荐在循环中使用)推荐使用场景:只读取Json中一个字段使用,如果实际需求中需要读取多个Json字段,推荐使用 ReadJson + GetNodeValue 两种组合理想情况下,一个Json只因读取一次,后续就是通过GetNodeValue获取字段值
To [ String, Int, Float, Bool ]
To [ String, Int, Float, Boll ]Array
源码里,很多地方是这样写的:
ParsedDataMap.Add(NewPath, { Value->AsString (), {}, {}, {}, { EValueType::String } }); 枚举值这种{}的构造初始化,打包Linux时,会有报错提示,可以通过配置项警用报错警示,但最后还是修改掉这种写法
ParsedDataMap.Add(NewPath, { Value->AsString (), {}, {}, {}, EValueType::String });