03Json序列化
JSON序列化
JSON是一种通用的数据格式结构。Unity中有很多工具可以将Class转换成JSON结构并持久化。本文主要记录一些Unity中可以用到的JSON序列化库工具,并且做一些简单的对比。以方便将来JSON相关的时候进行处理。
目前看到主要有一些JSON序列化工具
- JsonUtility
- LitJson
- Newtonsoft.Json
基础效率对比
工具名 | 序列化(ms) | 反序列化 | 数据大小 |
---|---|---|---|
次数 | $10^6$ | $10^5$ | |
JsonUtility | 4106 | 740 | 164 |
LitJson | 20096 | 8553 | 175 |
Newtonsoft.Json | 31540 | 4971 | 174 |
一个简单的序列化结果对比: 类型描述
|
|
序列化后的结果:
|
|
但每个工具都有细节,可以参看下面的说明:
JsonUtility
Unity自带的序列化工具,使用起来简单,速度是最快的。
官方文档说明,其序列化实例的类型必须是MonoBehaviour,ScriptableObject或者被Serializable attribute标注的普通Class/Struct。不支持的字段会被忽略,例如private field,static field以及那些被NonSerialized attribute标注的字段。
另一点是,尽量传递原始类型给该方法,因为有些情况下,其序列化结果不一定如预期一样。例如传递一个数组进入该方法,其不会产生一个包含每个元素的JSON数组,而是一个对象,包含了数组中对象的所有public field。
对于JsonUtility支持的序列化类型可参考Unity的Serialization Rule: https://docs.unity3d.com/Manual/script-Serialization.html
但是其实际支持的数据格式有限,支持以下类型:
- 基础数据类型
- 数字数据类型:
int,float,double,decimal,long
等 - 字符数据类型:
char,string
- Unity内置类型:
Vector2,Vector3,Quarteration
等
- 数字数据类型:
- 容器数据类型
- 支持
List,Array
集合类型 - 不支持
Dictionary,Query,stack
等集合类型,而且对应字段不会出现在json中。
- 支持
- 对于传入的类型,可以不用Serializable标注。但是如果其内部字段为某个类型,则对应类型需要用Serializable标注,才可以序列化。而且标注的类型被嵌套在List,Array中也可以被序列化。例如如下结构也可被序列化:
|
|
-
支持Enum枚举,但是值会转化成对应的数值值。
-
对于浮点数序列化后的结果会带上浮点误差。例如
10.54f=>10.539999961853028
导致序列化后的结构会比较大
LitJson序列化
LitJson是一个.Net库函数,用来处理往来Json格式的转换。 可以看到其速度对比JsonUtility要慢很多,。但是其支持对简单Dictionary的序列化操作。
- JsonUtility不支持字段,LitJson支持(但是键只能是字符串)。
- JsonUtility对自定义类型不要求有无参构造,LitJson则要求。
- JsonUtility存储空对象时会存储默认值而不是null,LitJson会存null。
Newtonsoft序列化
https://www.newtonsoft.com/json
Newonsoft库是这三个里面序列化速度最慢的,但是其反序列化速度还可以。参考一些论坛讨论,其对于大数据的序列化反序列化都还是很客观的。另一方面是,他支持的数据类型是最广泛的。支持Dictionary的各种泛型嵌套。除这些之外,其库函数还有各种使用支持。
其他
主要是一些网络上对三者序列化的讨论,有助于对于Json序列化的思考。
提到与所有性能问题一样,对于Json序列化考虑效率之前。先完整思考一下从架构,工程角度是否有必要去使用Json序列化。而不是单单思考这些方式够不够快上面。 例如对于三种序列化,他们所支持的数据结构是不太一样的。而这部分则是要根据我们的使用场景来确定用那种方式合适。
这个2015年的文章里面,也做了相同的测试。同时的是也补充测试了更大更复杂的数据。可以看到此时NewtonsoftJson序列化则是最快的。