protobuf與json互相轉換

Java

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

mavenjava

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

從protobuf轉jsongit

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

從json轉protobufgithub

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

C++

https://github.com/shramov/json2pbjson

 

Python

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

導入模塊pbjson.py便可使用。maven

ps. 原始模塊的pb2json函數會自動過濾protobuf中字段值爲空的數據。根據須要可註釋掉過濾代碼。ide

 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腳本就爲你幹這事提供了溫牀 ,下面會介紹這個過程:
一、造json文件,內容以下:
        #vi testjson2pb.json
        {
            "name":"scq",
            "age":30,
            "work_unit":"taobao",
            "class_mate":[
                {
                    "name":"jim",
                    "age":30
                }
            ]
        }

二、造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;
        }

三、生成protobuf對應python文件:
        #protoc -I=. --python_out=. testjson2pb.proto
        testjson2pb_pb2.py

四、編寫測試例子,具體以下:
        #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()

五、執行腳本,結果以下:
        #python testjson2pb.py
        
        是否是很簡單啊,自從有了這個腳本,再用不用擔憂人肉從json生成protobuf的問題了
        
      
原文連接: http://blog.chinaunix.net/uid-27714502-id-4067350.html
相關文章
相關標籤/搜索