关于protobufjson的信息

本篇文章给大家谈谈protobufjson,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

ProtoBuf简介

ProtoBuf是一种无关语言,无关平台的序列化结构数据的方法老哗,可用于通信协议、数据存储等

XML:数改段据较为冗余,需要成对的闭合标签

JSON:使用键值对方式,压缩了一定的数据空间并且具有可读性

ProtoBuf:适合高性能,对响应速度有要求的数据传输场景,ProtoBuf是二进制数据格式,需要核含誉解码和编码,数据本身不具有可读性,只能反序列化后才能读到真正的数据。序列化后的数据相比json和xml很小,适合网络传输;序列化和反序列化比json的处理速度更快。

XML、JSON 更注重数据结构化.

ProtoBuf更注重数据序列化,关注效率、空间、速度

数据类型分为两大类:

复合数据类型:枚举和message类型

标准数据类型:整型,浮点,字符串

规则的修饰符:

required 字段必须出现1次

optional 字段可出现0次或1次

repeated 字段可出现多次(包括0)

标准数据类型:

proto与python类型对应

例如:

[img]

了解一下ProtoBuf

我们在进行网络通信调用的时候,总是需要将内存的数据块经过序列化,转换成为一种可以通过网络流进行传输的格式。而这种格式在经过了传输之后再经过序列化,能还原成我们预想中的数据结构。

那么我们对于这种用于中间网络传输的数据格式就有一定的要求。首先它可以准确地描述数据内容,在此基础上我们则希望它尽量的小。

最开始流行起来的是XML,可扩展标记语言。由于它可以用来标记数据、定义数据类型,所以用户可以自己定义数据自己的语言,从而让对不同的数据结构化成统一的格式称为了可能。

而另外一个我们熟知的粗胡悔则是JSON(JavaScript Object Notation, JS 对象简谱)。尽管JSON中缺少了XML中的标签属性等描述方式,但是足够简介和清晰的层次结构使得其成为了必XML更受欢迎的数据交换格式。

同一份数据显然JSON的数据量比XML所使用的空间更少。那么空间省略在哪里呢?一方面是json使用更简单的字符来定义数据间的关联关系;另一方面是JSON减少了对数据类型的描述。但是丢少的数据类型再哪里呢?

以Java中的 OpenFeign 举例,JSON中缺少的类型定义被定义道程序中的接口中了。当进行序列化与反序列化时,JSON格式并不记录数据的类型,具体的数据类型在序列化方与反序列化方通过事先约定的接口来进行定义。这样就减少了信息传输过程中的信息量,从而让数据得以压缩。

但是JSON由于没有定义数据类型,所以在传输的过程中做亩实际上就都是文本流,那么这种方法还可以进一步压缩吗?

结合上文的讨论,我们先说结论:方法岩正是有的,并写当前的实现方式是ProtoBuf。但在此之前我们先来了解一下ProtoBuf。

我们可以先看看官方给出的定义与描述:

同样的,ProtoBuf也是一种支持序列化反序列化的方法,并且他具有很多优点:

实际上,ProtoBuf提供了一种通用的数据描述方式,这种定义数据的方式是通用的,就如同JSON或者XML一样。

接下来我们来来回答本节一开始的问题,针对JSON来说,ProtoBuf是如何将体积变得更小的呢?答案很简单,就是为数据序列化反序列化提供更多的先验知识。

本文暂不过度深入ProtoBuf原理,但是可以通过一张图来进行简要说明():

ProtoBuf中的数据是按顺序进行排列,而整体的结构为若干个field,每一个field中由 Tag-[Length]-Value 组成。Length是可选的,而是否存在Length是通过Tag的类型来决定的。也就是说如果是指定的类型,比如int64,那我们就可以知道Value的长度,也就不用在依靠Length来对其空间进行描述(redis中的压缩列表也是这个思想)。

那么field应该对应的是什么字段呢?这个则是在序列化与反序列化时在ProtoBuf的服务端与客户端之间进行预先定义的。而因为提前定义了field的类型、排序,所以field本身可以不用对字段名、字段位置进行描述,只需要根据字段类型选用合适的二进制序列化方法,将字段本身的value值进行序列化传输即可。

稍微总结一下:

ProtoBuf通过对传输字段的名称、顺序进行预定义,从而在传输结构中只需要顺序的记录每个字段的类型标签和二进制值。

尽管上文和官方中都是以XML或者JSON来对ProtoBuf进行对比。但是因为ProtoBuf本身就是二进制序列化方式,所以从压缩比上比较感觉有点欺负人。

对应的在Java中二进制常用的序列化器有Kryo和Hessian。但事实上,由于Kryo和Hessian中都需要对Java类名和字段信息进行存储。而ProtoBuf则只有Tag-Length-Value的数据对,且Value更是有针对性的特殊编码,所以空间占用小的很多。

Kryo是专门针对Java进行优化了的。所以在使用的便捷性上来说Kryo则更加方便。但ProtoBuf是跨平台的,且由于进行了字段的顺序定义,所以似的ProtoBuf定义后的接口是可以向前兼容的(只向后追加字段),而这种优势是Kryo所没有的。

ProtoBuf是跨语言的,使用ProtoBuf的第一步是先定一个 proto 文件 ,而由于ProtoBuf 2和3语言版本的不同,其定义格式会有所不同,具体的细节还是得参考官方文档:

对于ProtoBuf 3 的定义文档我们可以按如下方法定义:

其中message关键字是定义的文件名,而 string、int32则是预定的字段类型,repeated则是描述字段为可重复任意多次的字段。

ProtoBuf通过这种形式的文件定义了传输信息的文件结构。

但是之前小节中我们知道了ProtoBuf是通过 Tag-[Length]-Value 组成的数据组来进行信息传输的,那么proto文件中定义的内容如何转换为实际传输的对象呢?

ProtoBuf的做法是,为每一种语言提供一个生成器protoc。通过使用protoc则可以根据.proto文件生成为一组java文件。对应的官方语法演示样例为:

官方的生成参考为:

生成后的java文件将提供对应的实体以及数据的构造方法等文件,从而支持后续的使用。

需要注意的是,ProtoBuf是本质上是序列化方法,具体是通过Spring Cloud 的OpenFeign进行接口调用,还是通过grpc进行接口调用,都是可以的。

本文对ProtoBuff进行了概念的整理,并没有对每个细节都进行深入的梳理,可以当作概念科普来进行阅读。

为什么 protocol buffer比json快

浏览器和JS并不直接处理数据--尤其是遇到渣游内部服务时。我的观点是,结构化格式,例如谷歌的Protocol Buffers,是一个比JSON在编码方面更好的选择。如果你从来没有使用过Protocol Buffers,你可以参看 这里。不要担心,在说明为什么要选择Protocol Buffers而不是JSON之前,本文会简介如何使用在Ruby上使用它 。

Protocal Buffers的简短介绍

首先,什么是Protocol Buffers?文档中说:

“Protocol Buffers是一种以有效并可扩展的格式编码结构化数据的方式。”

Google开发了Protocol Buffers使用于内部的服务。 它是一种二进制格式允许你使用规范的语言定义一个模式,例如:

1 message Person {

2 required int32 id = 1;

3 required string name = 2;

4 optional string email = 3;

5 }

你能在命名空间中封装他们或者用上面的方式在顶层声明他们。这个片段定义了Person数据类型的模式,有三个字段:id, name和email。除了命名字段,你能提供一个类型决定数据怎样编码和在线上发送,在上面我们看到有int32类如竖销型和string类型。还提供了关键字进行验证和结构化(required 和optional )。字段被编号,这有助于向后兼容,我将在以后详细的介绍。

Protocol Buffers规范已被多种语言实现纤冲:Java,C,Go等。如果你四处找找最现代的语言都有实现的方式。Ruby也不例外,有几个不同的Gems使用Protocol Buffers编码和解码数据。这就意味着,这个规范可以在不同语言实现的系统间传递数据。

例如,Ruby Gem安装被称为ruby-protoc的二进制可以和主Protocol Buffers库组合使用(在OSX中brew install protobuf),自动的产生桩类文件用于编码和解码数据。正在运行的二进制proto文件产生以下的Ruby类:

view sourceprint?

01 #!/usr/bin/env ruby

02 # Generated by the protocol buffer compiler. DO NOT EDIT!

03 require 'protocol_buffers'

04

05 # forward declarations

06 class Person ::ProtocolBuffers::Message; end

07

08 class Person ::ProtocolBuffers::Message

09 set_fully_qualified_name "Person"

10

11 required :int32, :id, 1

12 required :string, :name, 2

13 optional :string, :email, 3

14 end

正如你所见,通过支持这种模式(Protocol Buffer格式),用来编码和解码信息,我们就能自动得到一个类(查看代码ProtocolBuffers::Message的基类在Gem中有更多细节的介绍)。我们已经看到了一些信息,那么就让我们再来仔细看看这些特征点,让我尝试说服你考虑Protocol Buffers——这里有5个理由。

json反序列化时如何创建对象

当json在反序列化时,默认选择类的无参构造函数创建类对象,当没有无参构造函数时会报错,@JsonCreator作用就是指定反序列化时用的参构造函数。构造方法的参数前面需要加上@JsonProperty,否则会报错。Json是一种轻量级的数据交换格式(也叫数据序列化方式)。Json采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。数据序列化格式还有:xml、protobuf,其中protobuf存储数据更为高效,在企业级项目中更常见。——RPC项目用的就是protobuf 序列化是将数据结构或是对象转换为二进制串(字节序列)的过程,也就是将具有一定结构的对象转换为可以存储或传输的形式。在序列化期间,对象将其当前状态写入到临时或持久性存储区(如硬盘)。这样我们就可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

反序列化就是上述的逆过程。

比如我们把json格式的对象转换成字符串,再转换成char*,这样就能在网络上传输,或者写进硬盘——由结构化的数据转成地址值反过来我们把从网络上接收到的字符串对象转成json对象,就是重新构建出json对象结构,这就是反序列化可以看到msg对应的值是一个json,两个json赋值给msg后变成了一个json,而且,js["msg"]["liu shuo"]的意义就是先访问js的键msg,再访问msg中的键liu shuo,还有就是,liu和zhang的顺序也被改了,因为两者在msg这个json里面就是键,是有顺序的在Asp.Net网站开发的过程中,很多时候会遇到对象的序列化和反序列化操作,Newtonsoft.Json组件是专门用来序列化和反序列化操作的一个功能册陵组件,引入这个DLL组件后,就可使用JsonConvert.DeserializeObject方法来反序列化字符串为对象,JsonConvert.DeserializeObject方法有2个重载方法签名,都是可用于C#中字符串的反序列化操作。

在具体需要字符串反序列化的地方调用JsonConvert.DeserializeObject方法。具体例子如下:有个前台传入的序列化字符串jsonStr,需要将之反序列化为TestModel对象,可使用下列语句进行实现。序列化(Serialization),有的人也称之为反解析。指的是将对象的状态信息转换为可以存储或传输的形式的过程。

而反序列化,有的人成为解析。指的就是序列化的逆过程。

图1. 序列化与反序列化

例如,定义如下结构体 book,我们可以创建一个实体对象,bookObj,此时 bookObj 是一个在程序中的实体对象。若我要存储这个对象,或者将其通过 HTTP 进行传输,我就需要将其进行序列化为可以进行存储或者传输的文件形式,例如 json。

package main

import (

"fmt"

"time"

)

type Book struct {

Name string

Author string

PublishTime time.Time

}

func main() {

bookObj := Book{

Name: "Go 语言基础入门",

Author: "fxtack",

PublishTime: time.Now(),

}

fmt.Println(bookObj)

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

若进行序列化,序列化后的 bookObj 对象的 JSON 格式为(注意,结构体字段名与 JSON 中的字段名并不是完全相等的):

{

"name": "Go 语言基础入门",

"author": "fxtack",

"publishTime": "2021-07-03T18:23:57.7451495+08:00"

}

1

2

3

4

5

1

2

3

4

5

这样我就可以通过存储和传输 json 来实现对 bookObj 对象的存储和传州蔽戚输了。

相应的,如果需要这个对象而读取 json 文件,或者传输的接收者收到这个对象的 json 并打算使用这个对象时,就需要通过反序列化,将其从并搏 json 的格式重新转化为程序中的对象。

解决protobuf忽略空返回值的问题

最近在用Kratos开发项目的时候遇到了问题,repeated类型的字段在值为空的情况下,字段被直接忽略掉了樱凯。

我希望的是即使为空的情况下也能返回一个空数含梁组,而不是直接把整个字段忽略掉,就像下面这样:

经过多方排查之后找到了问题所在,google会在生成pb.go文件时在json标签里插入 omitempty 属性,而json库在转换json时一旦遇到这个标签就会忽略掉空字段,这不符合我的需求,脊老唤所以把这个字段去掉就好了。

先写一个shell脚本来递归遍历api目录下的pb.go文件:

接着修改Makefile文件:

在api的最下面添加替换脚本,流程就是遍历scandir脚本查出来的pb.go文件,替换掉文件里所有的omitempty,然后将文件暂存为.tmp,最后再覆盖原文件。

今后每次执行make api时就会连带自动替换掉所有生成文件中的omitempty,免得每次手动替换麻烦又容易出错。

参考:

如何用python把protobuf转化json

直接利用python提供的json包,在django model的定义中增加一个方法toJSON,利用django model 能访问 _meta.fields 得到相关属性而得到,例子如下:

class Category(models.Model):

autoid = models.AutoField(primary_key=True)

email=models.CharField(max_length=150,blank=False)

comtype=models.CharField(max_length=20,blank=False)

catname=models.CharField(max_length=150,blank=False)

def __unicode__(self):

return '%s' % (self.catname)

def toJSON(self):

import json

return json.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

然后用django查出数据旁侍做,并转运衡谈薯换成json,代码如下:

row=models.Category.objects.get(autoid=23)

print row.toJSON()

关于protobufjson和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表