-
Notifications
You must be signed in to change notification settings - Fork 0
Cross Format Relay
github-actions[bot] edited this page Aug 13, 2026
·
2 revisions
cross_format::EventSink 是仓库自有的格式中立事件协议,让 JSON 与 CBOR
流式互转,不构造中间 Value 树,内存不随文档树增长。本页用一个具体转换
把机制走一遍。
常规的多格式引擎是"类型驱动"的:encode_with(&value, formats::Json) 需要
value 有类型。但有些场景你只想把字节转成字节——代理、日志、网关收到
JSON 要转发成 CBOR,中间谁都不想解析语义。硬要建一棵 Value 树再编码,大文档
的内存开销就是白付的。
EventSink 是"数据驱动"的答案:不需要类型、不建树,逐事件从源格式流到
目标格式。
pub trait EventSink {
fn null(&mut self) -> Result<()>;
fn boolean(&mut self, value: bool) -> Result<()>;
fn number(&mut self, value: Number) -> Result<()>;
fn string(&mut self, value: &str) -> Result<()>;
fn begin_array(&mut self) -> Result<()>;
fn end_array(&mut self) -> Result<()>;
fn begin_object(&mut self) -> Result<()>;
fn object_key(&mut self, key: &str) -> Result<()>;
fn end_object(&mut self) -> Result<()>;
}设计巧思:object_key 与 string 分离——防止目标格式意外接受 JSON 无法
表示的非字符串键。实现必须对非法事件顺序返回错误。
let json = br#"{"name":"NextJson","values":[1,2,3]}"#;
let cbor = cross_format::json_to_cbor(json)?;内部发生的事(json_into 逐事件喂给 CborSink):
json_into 读到 喂给 CborSink 的事件 CborSink 写出的 CBOR 字节
--------------------------------------------------------------
{ begin_object 0xA2 (map, 2 对)
"name" object_key("name") 0x64 'n' 'a' 'm' 'e'
"NextJson" string("NextJson") 0x69 "NextJson"
"values" object_key("values") 0x66 'v' 'a' 'l' 'u' 'e' 's'
[ begin_array 0x83 (array, 3 个)
1 number(1) 0x01
2 number(2) 0x02
3 number(3) 0x03
] end_array (无额外字节)
} end_object (无额外字节)
整个过程不出现任何中间 Value。CborSink 内部维护一个小状态机("现在在对象里
还是数组里、下一个该写键还是写值"),begin_object 时先数后续有多少个
object_key 才知道 map 长度前缀——所以 CborSink 也依赖"每个条目调用一次
object_key"这个契约。
-
JsonSink:事件 → 紧凑/美化 JSON; -
CborSink:事件 → RFC 8949 JSON 兼容 profile CBOR。
| 函数 | 作用 |
|---|---|
json_into(input, sink) |
JSON 输入流式喂给任意 EventSink
|
json_into_with_config(input, config, sink) |
带嵌套配置 |
cbor_into(input, sink) / cbor_into_with_max_depth
|
CBOR 输入流式喂给 sink |
json_to_cbor / json_to_cbor_writer
|
JSON → CBOR 字节/写出 |
cbor_to_json / cbor_to_json_writer / cbor_to_json_pretty / cbor_to_json_with_config
|
CBOR → JSON |
use nextjson::cross_format;
let json = br#"{"name":"NextJson","values":[1,2,3]}"#;
let cbor = cross_format::json_to_cbor(json)?;
let json_again = cross_format::cbor_to_json(&cbor)?;
assert_eq!(json_again, json);- 未转义 JSON 字符串在
json_into里以输入切片的直接借用传给 sink; - 转义字符串由 JSON 反转义必然物化——这是格式语义要求,文档不伪称零分配。
- 常规多格式引擎(Multi-Format Engine)是"类型驱动":需要
NsonSerialize/NsonDeserialize目标类型; -
EventSink是"数据驱动":只要目标格式能表示 JSON 数据模型,就能互转, 不需要类型、不建树。适合代理、日志、网关等"只转发不解析语义"的场景。
- CBOR 侧只接受 JSON 兼容 profile:原始 byte string、非字符串 map key、 非有限浮点、未知语义 tag 明确报错——防止 CBOR→JSON 时静默语义损失;
- 每条路径都有深度上限(默认 128)。