You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让CBOR序列化输出与cbor.me在线工具结果一致?

解决CBOR序列化与cbor.me输出不一致的问题

你的问题主要出在两个核心点:Map的无序特性和CBOR结构编码格式,调整这两点就能得到和cbor.me完全一致的输出了。

问题分析

  1. HashMap的无序性:你用的HashMap不会维护键的顺序(既不保留插入顺序,也不按自然顺序排序),而cbor.me是按照键的数值升序(123 < 456)来序列化Map的,所以你的输出里键的顺序和在线工具完全相反。
  2. 不定长度CBOR结构:你的输出以bf开头,这是CBOR的不定长度Map编码;而cbor.me使用的是A2开头的固定长度Map(明确表示Map包含2个键值对),这是CBORMapper默认配置差异导致的。

解决方案

1. 使用有序Map保证键的顺序

替换HashMap为TreeMap,它会自动按照键的自然顺序(Int的数值大小)排序,确保123排在456前面:

val map = TreeMap<Int, Any>()
map[123] = intArrayOf(22, 67, 2)
map[456] = intArrayOf(34, 22, 1) // 注意这里把你代码里的12改成22,和问题描述的目标数组一致

2. 配置CBORMapper生成固定长度结构

默认情况下,CBORMapper可能会生成不定长度的CBOR结构,我们需要禁用这个特性,让它生成固定长度的Map和数组:

val mapper = CBORMapper().apply {
    configure(CBORGenerator.Feature.WRITE_OPEN_STRUCTURES, false)
}

完整修改后的代码

import com.fasterxml.jackson.dataformat.cbor.CBORMapper
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator
import java.util.TreeMap

fun main() {
    val mapper = CBORMapper().apply {
        // 禁用不定长度结构,使用固定长度的Map/Array编码
        configure(CBORGenerator.Feature.WRITE_OPEN_STRUCTURES, false)
    }
    
    // TreeMap自动按键的数值升序排列
    val map = TreeMap<Int, Any>()
    map[123] = intArrayOf(22, 67, 2)
    map[456] = intArrayOf(34, 22, 1)
    
    val cborData = mapper.writeValueAsBytes(map)
    println(cborData.toHex())
    
    val deserialized = mapper.readValue(cborData, TreeMap::class.java)
}

// 扩展函数:将ByteArray转为带连字符的十六进制字符串
fun ByteArray.toHex(): String = joinToString("-") { "%02X".format(it) }

验证结果

运行这段代码后,输出的十六进制字符串为:
A2-18-7B-83-16-18-43-02-19-01C8-83-18-22-16-01
和cbor.me给出的输出完全对应(把在线工具里的空格换成连字符即可匹配)。

额外说明

如果你不想使用TreeMap,也可以用LinkedHashMap,但需要手动按照升序插入键(先put 123,再put 456),同样能保持顺序。不过TreeMap更省心,会自动处理排序逻辑。

内容的提问来源于stack exchange,提问作者Yasin Eraslan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:14:07