unity自带的JsonUtility.ToJson()无法序列化对象的自定义类型成员?

      在使用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;
}

      运行结果:

{“a”:1}
UnityEngine.Debug:Log(Object)
test:Start() (at Assets/Scripts/test.cs:15)

      可以看到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文件夹)。
unity自带的JsonUtility.ToJson()无法序列化对象的自定义类型成员?_第1张图片
      然后在脚本中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;
}

      运行结果:

{“a”:1,“b”:{“m”:2}}
UnityEngine.Debug:Log(Object)
test:Start() (at Assets/Scripts/test.cs:15)

      可以看到我们的msg可以正常编码了,即使有嵌套自定义类型对象。需要注意的是LitJson并不支持float型数据的编码,只支持double。如果你的msg里面含有float类型的数据,它会报错:

JsonException: Max allowed object depth reached while trying to export from type System.Single

      对于拥有大量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,添加就行了!

你可能感兴趣的:(unity自带的JsonUtility.ToJson()无法序列化对象的自定义类型成员?)