依然需要用户在机器安装protoc , 而不是自动下载protoc 。由于大部分场景都是用户已经有了自定义类型和基本类型以及组合类型构成的对象(树)需要被序列化 , 因此需要将用户类型对象转换成protobuf格式 。 这里面就有较大的开发成本 , 且每种需要都需要写一遍 , 代码冗长且易出错难维护 , 同时还存在大量数据转换和拷贝开销 。 另外转换过程没有考虑实际类型 , 因此还存在类型丢失的问题 , 比如LinkedList反序列化回来变成了ArrayList 。 下面是Java的序列化代码 , 大概需要130~150行 。return build(bar).build().toByteArray();public static ProtoMessage.Bar.Builder build(Bar bar) { ProtoMessage.Bar.Builder barBuilder = ProtoMessage.Bar.newBuilder(); if (bar.f1 == null) { barBuilder.clearF1();else { barBuilder.setF1(buildFoo(bar.f1));if (bar.f2 == null) { barBuilder.clearF2();else { barBuilder.setF2(bar.f2);if (bar.f3 == null) { barBuilder.clearF3();else { for (Foo foo : bar.f3) { barBuilder.addF3(buildFoo(foo));if (bar.f4 == null) { barBuilder.clearF4();else { bar.f4.forEach( (k v) -{ ProtoMessage.Foo.Builder fooBuilder1 = ProtoMessage.Foo.newBuilder(); fooBuilder1.setF1(v.f1); v.f2.forEach(fooBuilder1::putF2); barBuilder.putF4(k fooBuilder1.build()); );if (bar.f5 == null) { barBuilder.clearF5();else { barBuilder.setF5(bar.f5);if (bar.f6 == null) { barBuilder.clearF6();else { barBuilder.setF6(bar.f6);if (bar.f7 == null) { barBuilder.clearF7();else { barBuilder.setF7(bar.f7);if (bar.f8 == null) { barBuilder.clearF8();else { barBuilder.setF8(bar.f8);if (bar.f9 == null) { barBuilder.clearF9();else { for (short i : bar.f9) { barBuilder.addF9(i);if (bar.f10 ==null) { barBuilder.clearF10();else { barBuilder.addAllF10(bar.f10);return barBuilder;public static ProtoMessage.Foo.Builder buildFoo(Foo foo) { ProtoMessage.Foo.Builder builder = ProtoMessage.Foo.newBuilder(); if (foo.f1 == null) { builder.clearF1();else { builder.setF1(foo.f1);if (foo.f2 == null) { builder.clearF2();else { foo.f2.forEach(builder::putF2);return builder;public static Foo fromFooBuilder(ProtoMessage.Foo.Builder builder) { Foo foo = new Foo(); if (builder.hasF1()) { foo.f1 = builder.getF1();foo.f2 = builder.getF2Map(); return foo;public static Bar deserializeBar(byte[
bytes) throws InvalidProtocolBufferException { Bar bar = new Bar(); ProtoMessage.Bar.Builder barBuilder = ProtoMessage.Bar.newBuilder(); barBuilder.mergeFrom(bytes); if (barBuilder.hasF1()) { bar.f1 = fromFooBuilder(barBuilder.getF1Builder());if (barBuilder.hasF2()) { bar.f2 = barBuilder.getF2();bar.f3 = barBuilder.getF3BuilderList().stream() .map(ProtoState::fromFooBuilder) .collect(Collectors.toList()); bar.f4 = new HashMap(); barBuilder.getF4Map().forEach((k v) -bar.f4.put(k fromFooBuilder(v.toBuilder()))); if (barBuilder.hasF5()) { bar.f5 = barBuilder.getF5();if (barBuilder.hasF6()) { bar.f6 = barBuilder.getF6();if (barBuilder.hasF7()) { bar.f7 = barBuilder.getF7();if (barBuilder.hasF8()) { bar.f8 = barBuilder.getF8();bar.f9 = new short[barBuilder.getF9Count()
; for (int i = 0; ibarBuilder.getF9Count(); i++) { bar.f9[i
= (short) barBuilder.getF9(i);bar.f10 = barBuilder.getF10List(); return bar; Python序列化代码:大概130~150行
GoLang序列化代码:大概130~150行
即使之前没有针对该数据的自定义类型 , 也无法将protobuf生成的class直接用在业务代码里面 。 因为protobuf生成的class并不符合面向对象设计[12
, 无法给生成的class添加行为 。 这时候就需要定义额外的wrapper , 如果自动内部有其它自定义类型 , 还需要将这些类型转换成对应的wrapper , 这进一步限制了使用的灵活性 。对比Flatbuffer
Flatbuffer与protobuf一样 , 也需要大量的学习成本和开发成本:
安装flatc编译器[13
, 对于Linux环境 , 可能还需要进行源码编译安装flatc 。定义Schema namespace io.ray.fury.benchmark.state.generated;table FBSFoo { string:string; f2_key:[string
; // flatbuffers不支持map f2_value:[int
- 百度|“萝卜快跑”无人车出车祸 后轮被撞掉!官方回应:后车追尾
- 作为国内高新技术企业、两轮绿色能源网络布局的先行者|易马达重磅推出新国标智能换电车
- 百度|百度“萝卜快跑”无人车出车祸 后轮被撞掉
- 天使轮|36氪独家 | 天使轮红杉、云九、StarVC、高瓴同投,「光线云」再获前海基金Pre-A轮投资,全球首款云原生实时渲染引擎
- 3D打印|成立1年完成3轮融资,这家中国食品3D打印公司,为什么这么吃香?
- 阿斯麦尔|风水轮流转!ASML就我国发声,外媒:可以用EUV光刻机换
- 童文红|李楠这下放心了?怒喵科技获千万融资:投资方为联想创投
- 折叠屏|新一轮名单出炉,华为Harmony OS 3.0尝鲜版,新增17款设备可搭载
- 百度|派学车融资、YY学车倒闭,互联网驾培旱涝两重天
- 本文转自:人民网-湖南频道滑移装载机后轮悬空。|湖南长沙:聚焦工程机械 擦亮“智造之城”名片