在使用unity编写客户端网络模块时发现unity自带的Json序列化函数JsonUtility.ToJson()有一些坑,如果序列化对象的属性成员中有自定义类型对象,那么序列化后该成员会为空,无法编码。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour
{
void Start()
{
MyClassA msg = new MyClassA();
msg.a = 1;
msg.b.m = 2;
msg.b.n = 3.5f;
string s = JsonUtility.ToJson(msg);
Debug.Log(s);
}
}
public class MyClassA
{
public int a;
public MyClassB b = new MyClassB();
}
public class MyClassB
{
public int m;
public float n;
}
运行结果:
可以看到msg的成员b没有编码出来,因为JsonUtility.ToJson()无法识别嵌套的自定义类型,所以必须把MyClassA和MyClassB的对象分别编码,这样的话一条信息就不能根据自己的类型逻辑组织了。由此来看JsonUtility.ToJson()很鸡肋,一般的Json库都能够正常编码嵌套类型的,比如JavaScriptSerializer的Serialize()就很好用,不过需要引用System.Web.Extensions.dll外部库,然后using System.Web.Script.Serialization;就可以使用JavaScriptSerializer对象的Serialize()来编码了,反编码函数Deserialize()。
可惜的是当我把本地的System.Web.Extensions.dll拖到unity的Plugins目录后,发现unity无法载入这个外部库,可能是由于.net框架或者版本的问题,所以建议服务端使用JavaScriptSerializer来序列化消息。下面再介绍两种unity适用的Json函数。
第一种工具是LitJson,需要下载LitJson.dll外部库,然后拖入unity的Assets/Plugins目录(需要自己新建Plugins文件夹)。
然后在脚本中using LitJson;接着就可以使用JsonMapper.ToJson()函数来编码了,反序列化函数JsonMapper.ToObject(),代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
public class test : MonoBehaviour
{
void Start()
{
MyClassA msg = new MyClassA();
msg.a = 1;
msg.b.m = 2;
//msg.b.n = 3.5f;
string s = JsonMapper.ToJson(msg);
Debug.Log(s);
}
}
public class MyClassA
{
public int a;
public MyClassB b = new MyClassB();
}
public class MyClassB
{
public int m;
//public float n;
}
运行结果:
可以看到我们的msg可以正常编码了,即使有嵌套自定义类型对象。需要注意的是LitJson并不支持float型数据的编码,只支持double。如果你的msg里面含有float类型的数据,它会报错:
对于拥有大量float型数据的unity来说你可能会很恼怒,LitJson看来也很鸡肋。那么我再推荐一款Json工具Newtonsoft.Json,需要下载外部库Newtonsoft.Json.dll,然后放入Plugins文件夹中,接着using Newtonsoft.Json;就可以使用JsonConvert.SerializeObject()来编码了,反序列函数JsonConvert.DeserializeObject()。这个工具既可以编码float型,又可以编码嵌套自定义类型对象,完美!
LitJson链接:
https://pan.baidu.com/s/16cP8Vprx3WSar2dIY7F8oA
Newtonsoft.Json链接:
https://pan.baidu.com/s/1JZLB2SfMilnVGzbZGLZFqQ
System.Web.Extensions.dll在每个用户电脑本地目录(要选择合适的版本哦):
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.1\System.Web.Extensions.dll
记住unity只需要放入Assets/Plugins目录下,不需要在IDE工程中手动引用外部库(命名空间还是要的),而非unity工程,比如你的服务端工程则需要在IDE中手动添加外部引用,在资源管理器面板右击“引用”>“添加引用”>找到相应的dll,添加就行了!