-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathprotobuf_json_writer.py
126 lines (110 loc) · 3.38 KB
/
protobuf_json_writer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'''
Convert Google's protobuf Messages into commented JavaScript code.
'''
# groups are deprecated and not supported;
# Note that preservation of unknown fields is currently not available for Python (c) google docs
# TODO: Support extensions
__version__='0.0.1'
__author__='Paul Dovbush <dpp@dpp.su>'
from google.protobuf.descriptor import FieldDescriptor as _FieldDescriptor
from google.protobuf.reflection import GeneratedProtocolMessageType as _GeneratedProtocolMessageType
def _jsWriter_type_bytes():
return '""'
_jsWriter_type_bytes.__name__='bytes'
def _jsWriter_type_unicode():
return '""'
_jsWriter_type_unicode.__name__='unicode'
def _jsWriter_type_bool():
return 'false'
_jsWriter_type_bool.__name__='bool'
_jsWriter_types = {
_FieldDescriptor.TYPE_DOUBLE: float,
_FieldDescriptor.TYPE_FLOAT: float,
_FieldDescriptor.TYPE_INT64: long,
_FieldDescriptor.TYPE_UINT64: long,
_FieldDescriptor.TYPE_INT32: int,
_FieldDescriptor.TYPE_FIXED64: float,
_FieldDescriptor.TYPE_FIXED32: float,
_FieldDescriptor.TYPE_BOOL: _jsWriter_type_bool,
_FieldDescriptor.TYPE_STRING: _jsWriter_type_unicode,
# _FieldDescriptor.TYPE_MESSAGE: _msg2json,
_FieldDescriptor.TYPE_BYTES: _jsWriter_type_bytes,
_FieldDescriptor.TYPE_UINT32: int,
_FieldDescriptor.TYPE_ENUM: int,
_FieldDescriptor.TYPE_SFIXED32: float,
_FieldDescriptor.TYPE_SFIXED64: float,
_FieldDescriptor.TYPE_SINT32: int,
_FieldDescriptor.TYPE_SINT64: long,
}
from StringIO import StringIO
class jsWriter(StringIO):
_level = 0
def begin_msg(self, name):
self.write('/* %s */ {\n' % name)
self._level+=1
def end_msg(self):
self._level-=1
self.seek(self.pos-2)
self.write(self.print_indent+'\n}')
@property
def print_indent(self):
s=''
for i in range(0, self._level):
s+='\t'
return s
def _indent_value(self, value):
if type(value) in (str, unicode,):
value=value.replace('\n','\n'+self.print_indent)
return value.rstrip()
return value
def print_field(self, field_type, name, value, repeated):
self.write(self.print_indent+name+':')
if repeated:
if field_type:
self.write('/* %s[] */'%field_type)
self._level+=1
self.write(('[\n'+self.print_indent+'%s\n')%self._indent_value(value))
self._level-=1
self.write(self.print_indent+']')
else:
if field_type:
self.write('/* %s */'%field_type)
self.write('%s'%self._indent_value(value))
self.write(',\n')
def _msg2json(pb_msg):
jso = jsWriter()
try:
fields = list(pb_msg.fields)
# fields.extend(pb_msg.DESCRIPTOR.Extensions._known_extensions.values())
jso.begin_msg(pb_msg.name)
for field in fields:
if field.is_extension:
name = field.name+':ext'
else:
name = field.name
if field.type == _FieldDescriptor.TYPE_MESSAGE:
# ftype=field.message_type.name
ftype=None
value = _msg2json(field.message_type)
else:
ftype=_jsWriter_types[field.type].__name__
value = _jsWriter_types[field.type]()
jso.print_field(ftype, name, value, field.label == _FieldDescriptor.LABEL_REPEATED)
jso.end_msg()
except Exception, e:
jso.seek(0)
# e.args = (jso.read(),)
print jso.read()
raise
jso.seek(0)
return jso.read()
def proto2json(module):
res = ''
for pb_msg_name in dir(module):
pb_msg = getattr(module, pb_msg_name)
if not isinstance(pb_msg, _GeneratedProtocolMessageType):
continue
res += _msg2json(pb_msg.DESCRIPTOR) + '\n\n'
return res
if __name__ == '__main__':
from test import test_writer