DeepSeek教unity------MessagePack-02

news2025/3/26 19:02:35

内置支持类型:

对象序列化

MessagePack for C# 可以序列化你自己定义的公共类或结构体类型。默认情况下,可序列化的类型必须用 [MessagePackObject] 属性进行注解,成员需要用 [Key] 属性进行注解。键可以是索引(整数)或任意字符串。如果所有键都是索引,则使用数组进行序列化,这在性能和二进制大小方面具有优势。否则,将使用 MessagePack 映射(字典)【MessagePack maps (dictionaries) will be used】。

1、如果你使用 [MessagePackObject(keyAsPropertyName: true)],则成员不需要显式的 Key 属性,但会使用字符串键。

2、所有公共实例成员(字段和属性)都将被序列化。如果要忽略某些公共成员,可以使用 [IgnoreMember] 属性对成员进行注解。

3、任何可序列化的结构或类都必须具有公共访问权限;私有和内部结构及类不能被序列化!

4、你应该使用索引键(整数)还是字符串键?我们建议使用索引键以实现更快的序列化和更紧凑的二进制表示,这比字符串键更有优势。然而,在调试时,字符串键中的额外信息可能会非常有用。

/****************************************************
    文件:Test_02.cs
	作者:Edision
    日期:#CreateTime#
	功能:示例2
*****************************************************/

using MessagePack;
using UnityEngine;

public class Test_02 : MonoBehaviour
{
    public void Test()
    {
        // [10,20]
        Debug.Log($"【Test_02Logo】{MessagePackSerializer.SerializeToJson(new Sample1 { Foo = 10, Bar = 20 })}");

        // {"foo":10,"bar":20}
        Debug.Log($"【Test_02Logo】{MessagePackSerializer.SerializeToJson(new Sample2 { Foo = 10, Bar = 20 })}");

        // {"Foo":10}
        Debug.Log($"【Test_02Logo】{MessagePackSerializer.SerializeToJson(new Sample3 { Foo = 10, Bar = 20 })}");
    }

    [MessagePackObject]
    public class Sample1
    {
        [Key(0)]
        public int Foo { get; set; }
        [Key(1)]
        public int Bar { get; set; }
    }

    [MessagePackObject]
    public class Sample2
    {
        [Key("foo")]
        public int Foo { get; set; }
        [Key("bar")]
        public int Bar { get; set; }
    }

    [MessagePackObject(keyAsPropertyName: true)]
    public class Sample3
    {
        // 不需要 Key 属性
        public int Foo { get; set; }

        // 如果要忽略一个公共成员,可以使用 IgnoreMember 属性
        [IgnoreMember]
        public int Bar { get; set; }
    }

}

5、当类发生变化或扩展时,要注意版本控制。如果序列化的二进制数据中不存在某个键,MessagePackSerializer 会将成员初始化为其默认值,这意味着使用引用类型的成员可能会被初始化为 null。如果你使用索引键(整数),键应从 0 开始并依次递增。如果后期版本停止使用某些成员,你应该保留这些过时的成员(C# 提供了 Obsolete 属性来注解这些成员),直到所有其他客户端有机会更新并移除对这些成员的使用。此外,当索引键的值“跳跃”很大,导致序列中出现空隙时,这将对二进制大小产生负面影响,因为会在结果数组中插入 null 占位符。然而,你不应该重用已删除成员的索引,以避免客户端之间的兼容性问题或在尝试反序列化旧数据块时出现问题。

6、如果你不想显式地用 MessagePackObject/Key 属性进行注解,而是希望像使用 Json.NET 那样使用 MessagePack for C#,你可以利用无合约解析器。

7、如果你想序列化私有成员,可以使用其中一个 *AllowPrivate 解析器。

/****************************************************
    文件:Test_03.cs
	作者:Edision
    日期:#CreateTime#
	功能:示例3:索引空隙和结果占位符的例子
*****************************************************/

using MessagePack;
using MessagePack.Resolvers;
using System;
using UnityEngine;

public class Test_03 : MonoBehaviour
{
    public void Test()
    {
        //************************************************************************//
        // [null,null,null,0,null,null,null,null,null,null,0]
        Debug.Log($"【Test_03Logo】" + MessagePackSerializer.SerializeToJson(new IntKeySample()));

        //************************************************************************//
        var data = new ContractlessSample { MyProperty1 = 99, MyProperty2 = 9999 };
        var bin = MessagePackSerializer.Serialize(data, MessagePack.Resolvers.ContractlessStandardResolver.Options);
        // {"MyProperty1":99,"MyProperty2":9999}
        Debug.Log($"【Test_03Logo】{MessagePackSerializer.ConvertToJson(bin)}");

        //************************************************************************//
        // 你也可以将 ContractlessStandardResolver 设置为默认解析器。
        // (全局状态;不推荐在编写库代码时使用)
        MessagePackSerializer.DefaultOptions = MessagePack.Resolvers.ContractlessStandardResolver.Options;
        var bin2 = MessagePackSerializer.Serialize(data);
        // {"MyProperty1":99,"MyProperty2":9999}
        Debug.Log($"【Test_03Logo】{MessagePackSerializer.ConvertToJson(bin2)}");

        //************************************************************************//

        var privateData = new PrivateSample();
        privateData.SetX(9999);
        //你可以选择 StandardResolverAllowPrivate 或 ContractlessStandardResolverAllowPrivate
        var privateBin = MessagePackSerializer.Serialize(privateData, ContractlessStandardResolverAllowPrivate.Options);
        Debug.Log($"【Test_03Logo】{MessagePackSerializer.ConvertToJson(privateBin)}");//【Test_03Logo】[9999]
        // 反序列化
        var deserializedData = MessagePackSerializer.Deserialize<PrivateSample>(privateBin, ContractlessStandardResolverAllowPrivate.Options);
        deserializedData.PrintPrivateField(); // 输出:Test_03Logo】PrivateField: 9999
    }

    [MessagePackObject]
    public class IntKeySample
    {
        [Key(3)]
        public int A { get; set; }
        [Key(10)]
        public int B { get; set; }
    }

    /// <summary>
    /// 无合约示例
    /// </summary>
    public class ContractlessSample
    {
        public int MyProperty1 { get; set; }
        public int MyProperty2 { get; set; }
    }
}

[MessagePackObject]
public partial class PrivateSample
{
    [Key(0)]
    int x;

    public void SetX(int v)
    {
        x = v;
    }

    public int GetX()
    {
        return x;
    }

    public void PrintPrivateField()
    {
        Debug.Log($"Test_03Logo】PrivateField: {x}");
    }
}

序列化回调

实现 IMessagePackSerializationCallbackReceiver 接口的对象将在序列化/反序列化期间收到 OnBeforeSerialize 和 OnAfterDeserialize 调用。

    
    public void Test()
    {
        var mc = new SampleCallback { Key = 0 };
        byte[] bytes =  MessagePackSerializer.Serialize(mc);
        SampleCallback sc = MessagePackSerializer.Deserialize<SampleCallback>(bytes);
    }

    [MessagePackObject]
    public class SampleCallback : IMessagePackSerializationCallbackReceiver
    {
        [Key(0)]
        public int Key { get; set; }

        public void OnBeforeSerialize()
        {
            Debug.Log("OnBefore");
        }

        public void OnAfterDeserialize()
        {
            Debug.Log("OnAfter");
        }
    }

总结

  • 索引间隙会导致 MessagePack 在序列化时插入占位符。

  • 反序列化时,占位符会被转换为对应类型的默认值。

  • 在设计数据结构时,尽量避免不必要的索引间隙,以减少序列化后的数据大小和处理开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

H5应用抓包及调试技巧

由于图片和格式解析问题&#xff0c;可前往 阅读原文 在现代移动互联网时代&#xff0c;H5 应用以其跨平台、轻量化、快速迭代的特性&#xff0c;成为移动开发的重要一环。然而&#xff0c;随着功能的复杂化和用户体验要求的提升&#xff0c;H5应用的调试也面临着诸多挑战&…

自学Java-面向对象高级(final、单例类、枚举类、抽象类、接口)

自学Java-面向对象高级&#xff08;final、单例类、枚举类、抽象类、接口&#xff09; 一、final关键字1、认识final关键字2、final修饰变量的注意3、常量 二、单例类&#xff08;设计模式&#xff09;1、设计模式的概念2、单例设计模式3、单例类有很多形式4、懒汉式单例类5、小…

docker下部署kong+consul+konga 报错问题处理

前言&#xff1a; 由于在docker下部署一些项目比较特殊&#xff0c;特别是网络这一块&#xff0c;如果没有搞清楚&#xff0c;是很容易出问题的。 先上docker-compose 编排 这里的docker-compose for kong可以在 kong-compose 获取代码 version: 3.9x-kong-config:&kong…

网络优化工作流程

DT路测 移动测试&#xff08;Drive Test&#xff09; CQT 定点测试&#xff08;通信质量测试&#xff09; DT 测试不能体现实际话务质量&#xff1a;回音、串音等网络问题不能通过 DT 测试发现&#xff0c;因此 CQT 拨打测试是 DT 测试很好的补充&#xff0c;也是目前室内外测…

React入门 - 0.React简介

React入门 - React简介 A Brief Introduction to React By JacksonML 1. 关于React React是一个知名的Web框架。众所周知&#xff0c;jQuery, Angular, Vue等框架都曾闪亮登场&#xff0c;并且&#xff0c;都仍然在全球市场占有一席之地。React这个颇有担当的新锐&#xff0…

SpringCloud系列教程:微服务的未来(二十四)Direct交换机、Topic交换机、声明队列交换机

前言 在现代消息队列系统中&#xff0c;交换机是实现消息传递和路由的核心组件。本文将重点探讨三种常见的交换机类型&#xff1a;Direct交换机、Topic交换机和声明队列交换机。通过对这三种交换机的详细分析&#xff0c;我们将学习它们的工作原理、应用场景以及如何在实际项目…

Sojson高级加密技术科普

1. 引言 什么是Sojson&#xff1f; Sojson是一款用于JavaScript代码加密与混淆的工具&#xff0c;它能够有效保护前端代码的知识产权&#xff0c;避免开发者的心血被随意窃取。 为什么需要代码加密&#xff1f; 在当今的互联网环境下&#xff0c;代码被轻易复制、篡改或逆向…

mysql多主集群 galera cluster for mysql 8安装配置启动重启集群

[TOC] 一、安装mysql 1、安装 系统环境&#xff1a; Ubuntu 18.04 64位 MySQL 8.0.19 下载MySQL APT安装配置包 首先访问 https://dev.mysql.com/downloads/repo/apt/ 获取配置包下载地址 wget https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb sudo dpkg -i mysq…

mybatis 入门案例

前言 我们清楚 mybatis 是一个持久层框架&#xff0c;可以非常便捷的操作数据库。如最常见的对数据进行增删改查操作。 项目准备 1 在mybatis 数据库 创建 user 用户表 并插入以下两条数据 以下是一个user.sql 脚本文件如何使用 脚本文件可以参照MySQL数据库的备份与还原_控…

Python使用Flask结合DeepSeek开发

一、背景 我之前关于DeepSeek使用ollama部署的文章大家可以把DeepSeek大模型部署起来。那么ollama还提供了可以调用对应部署模型的API接口。我们可以基于这些接口&#xff0c;做自己的二次开发。使用pythonflaskollama就可以进行模型对话调用。并且前端采用SSE的技术&#xff0…

前端常见面试题-2025

vue4.0 Vue.js 4.0 是在 2021 年 9 月发布。Vue.js 4.0 是 Vue.js 的一个重要版本&#xff0c;引入了许多新特性和改进&#xff0c;旨在提升开发者的体验和性能。以下是一些关键的更新和新特性&#xff1a; Composition API 重构&#xff1a;Vue 3 引入了 Composition API 作为…

大模型开发实战篇7:语音识别-语音转文字

语音识别大模型&#xff0c;是人工智能领域的一项重要技术&#xff0c;它能够将人类的语音转换为文本。近年来&#xff0c;随着深度学习技术的不断发展&#xff0c;语音识别大模型取得了显著的进展&#xff0c;并在各个领域得到了广泛应用。 主流语音识别大模型 目前&#xf…

QML 部件获得焦点触发的全局槽函数 onActiveFocusItemChanged

在qml的window窗口中&#xff0c;假如添加里许多其他部件&#xff0c;当这些部件改变时&#xff0c;会有一个全局部件焦点改变槽函数触发&#xff0c;就是 onActiveFocusItemChanged 可以通过此槽函数就可以知道当前焦点在哪一个部件上&#xff0c;也可以做一些自动化测试等&…

如何用ClassFinal加密JAR保护知识产权!

0.前言 凌晨三点的办公室&#xff0c;咖啡杯底凝着褐色的残渍&#xff0c;键盘上跳跃的手指突然停滞。张工程师盯着屏幕上的反编译窗口&#xff0c;自己耗时三个月开发的规则引擎此刻像被解剖的标本般赤裸裸摊开——这正是上周交付给客户的jar包。当.class文件以伪代码形式暴露…

轨迹优化 | 基于LBFGS优化器的无约束路径平滑(附ROS C++仿真)

目录 0 专栏介绍1 LBFGS优化器1.1 拟牛顿法框架1.2 LBFGS-Lite库 2 基于LBFGS的轨迹优化3 ROS C仿真 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及更高阶的运动规划算法轨迹优化实战&#xff0c;包括&#xff1a;曲线生成、碰撞检测…

Vue2到Vue3:无痛升级之路

为什么要从 Vue2 升级到 Vue3 Vue 3 带来了众多令人瞩目的改进和新特性&#xff0c;这些优势使得升级到 Vue 3 对项目的长期发展具有重要意义。 性能显著提升&#xff1a;Vue 3 采用了基于 Proxy 的响应式系统&#xff0c;相比 Vue 2 使用的 Object.defineProperty&#xff0c…

第28篇 基于ARM A9处理器用C语言实现中断<四>

Q&#xff1a;可以改变上一期实验工程里红色LED计数的速率吗&#xff1f; A&#xff1a;在按键中断服务程序中使HPS Timer 0停止计数&#xff0c;修改定时器中使用的预设计数值&#xff0c;然后重启定时器&#xff1b;所有的修改都是在按键中断服务程序中完成。主程序和其他…

时间序列分析(四)——差分运算、延迟算子、AR(p)模型

此前篇章&#xff1a; 时间序列分析&#xff08;一&#xff09;——基础概念篇 时间序列分析&#xff08;二&#xff09;——平稳性检验 时间序列分析&#xff08;三&#xff09;——白噪声检验 一、差分运算 差分运算的定义&#xff1a;差分运算是一种将非平稳时间序列转换…

《深度学习》——调整学习率和保存使用最优模型

调整学习率 在使用 PyTorch 进行深度学习训练时&#xff0c;调整学习率是一个重要的技巧&#xff0c;合适的学习率调整策略可以帮助模型更好地收敛。 PyTorch 提供了多种调整学习率的方法&#xff0c;下面将详细介绍几种常见的学习率调整策略及实例代码&#xff1a; torch.opt…

零风险把数据盘挂载给根分区,给生产环境服务器扩容

背景 刚买服务器时&#xff0c;用户量不大&#xff0c;所以结合预算不多情况下&#xff0c;都是默认买个小点的系统盘挂载到服务器上&#xff0c;&#xff08;或者默认服务器的40G&#xff09;&#xff0c;等到某一天业务量上来之后&#xff0c;发现抓肘见襟给自己一手措不及防…