• protobuf与json互相转换


    Java

    http://code.google.com/p/protobuf-java-format/

    maven

    <dependency>
    <groupId>com.googlecode.protobuf-java-format</groupId>
    <artifactId>protobuf-java-format</artifactId>
    <version>1.2</version>
    </dependency>

    从protobuf转json

    Message someProto =SomeProto.getDefaultInstance();
    String jsonFormat =JsonFormat.printToString(someProto);

    从json转protobuf

    Message.Builder builder =SomeProto.newBuilder();
    String jsonFormat = _load json document from a source_;
    JsonFormat.merge(jsonFormat, builder);

    C++

    https://github.com/shramov/json2pb

     

    Python

    https://github.com/NextTuesday/py-pb-converters

    导入模块pbjson.py即可使用。

    ps. 原始模块的pb2json函数会自动过滤protobuf中字段值为空的数据。根据需要可注释掉过滤代码。

     pbjson .py:

    import simplejson
      from google.protobuf.descriptor import FieldDescriptor as FD
       
      class ConvertException(Exception):
      pass
       
      def dict2pb(cls, adict, strict=False):
      """
      Takes a class representing the ProtoBuf Message and fills it with data from
      the dict.
      """
      obj = cls()
      for field in obj.DESCRIPTOR.fields:
      if not field.label == field.LABEL_REQUIRED:
      continue
      if not field.has_default_value:
      continue
      if not field.name in adict:
      raise ConvertException('Field "%s" missing from descriptor dictionary.'
      % field.name)
      field_names = set([field.name for field in obj.DESCRIPTOR.fields])
      if strict:
      for key in adict.keys():
      if key not in field_names:
      raise ConvertException(
      'Key "%s" can not be mapped to field in %s class.'
      % (key, type(obj)))
      for field in obj.DESCRIPTOR.fields:
      if not field.name in adict:
      continue
      msg_type = field.message_type
      if field.label == FD.LABEL_REPEATED:
      if field.type == FD.TYPE_MESSAGE:
      for sub_dict in adict[field.name]:
      item = getattr(obj, field.name).add()
      item.CopyFrom(dict2pb(msg_type._concrete_class, sub_dict))
      else:
      map(getattr(obj, field.name).append, adict[field.name])
      else:
      if field.type == FD.TYPE_MESSAGE:
      value = dict2pb(msg_type._concrete_class, adict[field.name])
      getattr(obj, field.name).CopyFrom(value)
      else:
      setattr(obj, field.name, adict[field.name])
      return obj
       
       
      def pb2dict(obj):
      """
      Takes a ProtoBuf Message obj and convertes it to a dict.
      """
      adict = {}
      if not obj.IsInitialized():
      return None
      for field in obj.DESCRIPTOR.fields:
      if not getattr(obj, field.name):
      continue
      if not field.label == FD.LABEL_REPEATED:
      if not field.type == FD.TYPE_MESSAGE:
      adict[field.name] = getattr(obj, field.name)
      else:
      value = pb2dict(getattr(obj, field.name))
      if value:
      adict[field.name] = value
      else:
      if field.type == FD.TYPE_MESSAGE:
      adict[field.name] =
      [pb2dict(v) for v in getattr(obj, field.name)]
      else:
      adict[field.name] = [v for v in getattr(obj, field.name)]
      return adict
       
       
      def json2pb(cls, json, strict=False):
      """
      Takes a class representing the Protobuf Message and fills it with data from
      the json string.
      """
      return dict2pb(cls, simplejson.loads(json), strict)
       
       
      def pb2json(obj):
      """
      Takes a ProtoBuf Message obj and convertes it to a json string.
      """
      return simplejson.dumps(pb2dict(obj), sort_keys=True, indent=4)


    json2pb   

     在功能测试或集成测试中,用json造输入数据,然后moc测试脚本将json转化为protobuf发送给被测试模块或服务,是非常常见的功能测试手段。
            如果测试脚本用Python来写的话,一般的做法是用的Python调用json模块中函数解析json文件,然后新建protobuf对象,依次填写各字段,然后发送出去。
            当然如果愿意造上面的轮子也没关系,如果想偷懒也是可行的,pbjson.py脚本就为你干这事提供了温床,下面会介绍这个过程:
    1、造json文件,内容如下:
            #vi testjson2pb.json
            {
                "name":"scq",
                "age":30,
                "work_unit":"taobao",
                "class_mate":[
                    {
                        "name":"jim",
                        "age":30
                    }
                ]
            }

    2、造protobuf文件,内容如下:
            #vi testjson2pb.proto
            //class mate
            package json2pb;
            message PersonInfo {
                //my name
                required string name = 1;
                //my age
                optional int32 age = 2;
                //my work unit
                optional string work_unit = 3;
                message ClassMate {
                    //name
                    optional string name = 1;
                    //age
                    optional uint32 age = 2;
                }
                repeated ClassMate class_mate = 4;
            }

    3、生成protobuf对应python文件:
            #protoc -I=. --python_out=. testjson2pb.proto
            testjson2pb_pb2.py

    4、编写测试例子,具体如下:
            #vi testjson2pb.py
            -------------------------------------------------------------------------------------------------
            #!/usr/bin/env python
            # coding=utf-8

            import sys
            import logging
            import os
            import time
            import string
            import pbjson
            import simplejson
            import testjson2pb_pb2

            def main():
                f = file("testjson2pb.json")
                s = simplejson.load(f)
                f.close
                t = pbjson.dict2pb(testjson2pb_pb2.PersonInfo, s)
                print t

            if __name__  ==  "__main__":
                main()

    5、执行脚本,结果如下:
            #python testjson2pb.py
            
            是不是很简单啊,自从有了这个脚本,再用不用担心人肉从json生成protobuf的问题了
            
          
    原文链接:http://blog.chinaunix.net/uid-27714502-id-4067350.html

  • 相关阅读:
    Android Studio打开非本机项目比较慢的问题。
    Servlet实现重定向的两种方式
    Servlet实现定时刷新到另外一个页面response.setHeader("refresh", "3;url=/...")
    Servlet实现自动刷新功能
    自己实现一个验证码功能
    使用Servlet实现图片下载
    数据库备份的几种方法
    servlet实现的三种方式对比(servlet 和GenericServlet和HttpServlet)
    java中this的用法如:this.name=name
    步骤一:下载jdk并安装和配置java环境变量
  • 原文地址:https://www.cnblogs.com/catkins/p/5270413.html
Copyright © 2020-2023  润新知