【问题标题】:Serializing structs as compactly as possible [closed]尽可能紧凑地序列化结构[关闭]
【发布时间】:2020-04-06 12:54:16
【问题描述】:

我想为多人游戏序列化和反序列化各种结构。我目前正在使用统一的 json 序列化:

public static T GetObject<T>(byte[] bytes) {
        T t = JsonUtility.FromJson<T>(encoding.GetString(bytes));
        return t;
    }

    public static byte[] GetBytes(object obj) {
        string json = JsonUtility.ToJson(obj);
        return encoding.GetBytes(json);
    }

它工作得很好,但问题是 json 显然不是那么紧凑。我尝试了 BinaryFormatter 和 Marshalling,但 BinaryFormatter 创建了一个我认为不需要的大标题,而且 Marshalling 不适用于结构内的数组和结构。我希望系统尽可能灵活,因为经常添加新结构。

json 序列化与数组、结构内部的结构以及字符串或向量等类型完美配合。所以我正在寻找的是类似于 json 序列化器但更紧凑的东西。

示例结构:

struct A {
    Vector3 position;
    string name;
}
struct B {
    uint id;
    A[] examples;
}

【问题讨论】:

  • 这个结构是什么样的?你可以添加属性吗? protobuf 在很多情况下都能很好地工作,而且 protobuf-net 通常很容易通过添加一些属性来改造现有类型;如果你有你的结构的例子,我可能会更具体
  • 是的,我可以添加属性,我会研究 protobuf。我可以给出一些示例结构,但我希望能够随着时间的推移添加更多结构。
  • (随着时间的推移添加更多)我明白;我只是想a:衡量它的适用性,b:帮助你开始
  • 我加了一个例子
  • 您好,两个问题:-您是否有理由需要使用 json-您打算如何在客户端和服务器之间传输我在问,因为有很多选项可以使它变得更好,例如 zipstreaming json 字符串很容易,从根本无法工作的网络服务器压缩回复,到 BSON 或 protobuf,我知道您不想使用普通的 C# 内置序列化,或者这是一个选项?等等等等

标签: c# unity3d serialization


【解决方案1】:

protobuf-net 可能是一个选项;鉴于问题中的示例,这可能是:

[ProtoContract]
struct A
{
    [ProtoMember(1)]
    public Vector3 position;
    [ProtoMember(2)]
    public string name;
}
[ProtoContract]
struct B
{
    [ProtoMember(1)]
    public uint id;
    [ProtoMember(2)]
    public A[] examples;
}

用法类似于:

static class P
{
    static void Main()
    {
        // Vector3 may be a nuicanse, as it doesn't fit any normal patterns; tweak it...
        // (only need to do this once somewhere early on in the program)
        RuntimeTypeModel.Default.Add(typeof(Vector3), false)
            .Add(nameof(Vector3.x), nameof(Vector3.y), nameof(Vector3.z));

        // test object
        var original = new B {
            id = 42,
            examples = new [] {
                new A {
                    position = new Vector3(1, 2, 3),
                    name = "abc"
                }
            }
        };
        var ms = new MemoryStream();
        // serialize
        Serializer.Serialize(ms, original);
        // show the hex (normally you wouldn't do this - you'd just use the binary
        Console.WriteLine(BitConverter.ToString(ms.GetBuffer(), 0, (int)ms.Length));
        // deserialize (remembering that MemoryStream needs to be rewound)
        ms.Position = 0;
        var b = Serializer.Deserialize<B>(ms);
        Console.WriteLine(b.id);
        var a = b.examples.Single();
        Console.WriteLine(a.name);
        Console.WriteLine(a.position.x);
        Console.WriteLine(a.position.y);
        Console.WriteLine(a.position.z);
    }
}

这给了我 26 个字节,而不是通过 JsonConvert.SerializeObject 获得 74 个字节的 UTF-8,用于相同的有效负载。

您可能想尝试使用或不使用 Vector3 的自定义设置步骤。一些额外的注意事项:如果您使用的是 AOT,那么执行运行时元编程的 any 工具可能会遇到一些问题,而 protobuf-net 可以广泛使用这些工具。但是设置它以在您的环境中测试它是相对容易的,至少!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 2011-03-15
    相关资源
    最近更新 更多