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

39 篇文章 1 订阅

在使用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,添加就行了!
 

Unity中的protobuf序列化是一种将数据结构转化为字节流的方法,以便在网络传输、存储或在不同平台之间传递数据。它基于Google的protobuf (Protocol Buffers)协议,能够高效地序列化和反序列化复杂的数据结构。 在Unity中使用protobuf序列化需要进行以下几个步骤: 1. 定义消息结构:首先需要在.proto文件中定义要序列化的数据结构。这包括定义消息的字段、枚举、嵌套消息等。可以指定每个字段的类型(整数、浮点数、字符串等)和标签(用于标识字段的唯一性)等信息。 2. 编译.proto文件:使用protobuf编译器将.proto文件编译为相应语言的代码。在Unity中可以使用Protobuf-net等第三方插件来生成C#代码。 3. 序列化数据:在需要序列化数据的地方,将数据按照定义好的消息结构进行赋值,并使用protobuf提供的方法将其序列化为字节流。 4. 反序列化数据:在接收端或需要解析数据的地方,使用protobuf提供的方法将字节流反序列化为消息对象,然后可以通过读取字段的方式获取其中的数据。 使用unity protobuf序列化的好处是: 1. 空间效率高:protobuf采用二进制格式进行序列化,可以将数据压缩为较小的字节流,减少网络传输和存储的空间成本。 2. 速度快:protobuf的序列化和反序列化速度较快,可以更有效地处理大量的数据。 3. 跨平台兼容性好:使用protobuf序列化后的数据可以在不同平台、不同语言之间共享和传输,无需担心兼容性问题。 总之,Unity中的protobuf序列化是一种在网络传输和数据存储中高效、方便的数据序列化方法,可以帮助开发者更好地处理数据结构和跨平台数据传输的问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值