json_format.py
Go to the documentation of this file.
1 # Protocol Buffers - Google's data interchange format
2 # Copyright 2008 Google Inc. All rights reserved.
3 # https://developers.google.com/protocol-buffers/
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 """Contains routines for printing protocol messages in JSON format.
32 
33 Simple usage example:
34 
35  # Create a proto object and serialize it to a json format string.
36  message = my_proto_pb2.MyMessage(foo='bar')
37  json_string = json_format.MessageToJson(message)
38 
39  # Parse a json format string to proto object.
40  message = json_format.Parse(json_string, my_proto_pb2.MyMessage())
41 """
42 
43 __author__ = 'jieluo@google.com (Jie Luo)'
44 
45 # pylint: disable=g-statement-before-imports,g-import-not-at-top
46 try:
47  from collections import OrderedDict
48 except ImportError:
49  from ordereddict import OrderedDict # PY26
50 # pylint: enable=g-statement-before-imports,g-import-not-at-top
51 
52 import base64
53 import json
54 import math
55 
56 from operator import methodcaller
57 
58 import re
59 import sys
60 
61 import six
62 
63 from google.protobuf import descriptor
64 from google.protobuf import symbol_database
65 
66 
67 _TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
68 _INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32,
69  descriptor.FieldDescriptor.CPPTYPE_UINT32,
70  descriptor.FieldDescriptor.CPPTYPE_INT64,
71  descriptor.FieldDescriptor.CPPTYPE_UINT64])
72 _INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64,
73  descriptor.FieldDescriptor.CPPTYPE_UINT64])
74 _FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT,
75  descriptor.FieldDescriptor.CPPTYPE_DOUBLE])
76 _INFINITY = 'Infinity'
77 _NEG_INFINITY = '-Infinity'
78 _NAN = 'NaN'
79 
80 _UNPAIRED_SURROGATE_PATTERN = re.compile(six.u(
81  r'[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]'
82 ))
83 
84 _VALID_EXTENSION_NAME = re.compile(r'\[[a-zA-Z0-9\._]*\]$')
85 
86 
87 class Error(Exception):
88  """Top-level module error for json_format."""
89 
90 
92  """Thrown if serialization to JSON fails."""
93 
94 
96  """Thrown in case of parsing error."""
97 
98 
100  message,
101  including_default_value_fields=False,
102  preserving_proto_field_name=False,
103  indent=2,
104  sort_keys=False,
105  use_integers_for_enums=False,
106  descriptor_pool=None):
107  """Converts protobuf message to JSON format.
108 
109  Args:
110  message: The protocol buffers message instance to serialize.
111  including_default_value_fields: If True, singular primitive fields,
112  repeated fields, and map fields will always be serialized. If
113  False, only serialize non-empty fields. Singular message fields
114  and oneof fields are not affected by this option.
115  preserving_proto_field_name: If True, use the original proto field
116  names as defined in the .proto file. If False, convert the field
117  names to lowerCamelCase.
118  indent: The JSON object will be pretty-printed with this indent level.
119  An indent level of 0 or negative will only insert newlines.
120  sort_keys: If True, then the output will be sorted by field names.
121  use_integers_for_enums: If true, print integers instead of enum names.
122  descriptor_pool: A Descriptor Pool for resolving types. If None use the
123  default.
124 
125  Returns:
126  A string containing the JSON formatted protocol buffer message.
127  """
128  printer = _Printer(
129  including_default_value_fields,
130  preserving_proto_field_name,
131  use_integers_for_enums,
132  descriptor_pool)
133  return printer.ToJsonString(message, indent, sort_keys)
134 
135 
137  message,
138  including_default_value_fields=False,
139  preserving_proto_field_name=False,
140  use_integers_for_enums=False,
141  descriptor_pool=None):
142  """Converts protobuf message to a dictionary.
143 
144  When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
145 
146  Args:
147  message: The protocol buffers message instance to serialize.
148  including_default_value_fields: If True, singular primitive fields,
149  repeated fields, and map fields will always be serialized. If
150  False, only serialize non-empty fields. Singular message fields
151  and oneof fields are not affected by this option.
152  preserving_proto_field_name: If True, use the original proto field
153  names as defined in the .proto file. If False, convert the field
154  names to lowerCamelCase.
155  use_integers_for_enums: If true, print integers instead of enum names.
156  descriptor_pool: A Descriptor Pool for resolving types. If None use the
157  default.
158 
159  Returns:
160  A dict representation of the protocol buffer message.
161  """
162  printer = _Printer(
163  including_default_value_fields,
164  preserving_proto_field_name,
165  use_integers_for_enums,
166  descriptor_pool)
167  # pylint: disable=protected-access
168  return printer._MessageToJsonObject(message)
169 
170 
171 def _IsMapEntry(field):
172  return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
173  field.message_type.has_options and
174  field.message_type.GetOptions().map_entry)
175 
176 
177 class _Printer(object):
178  """JSON format printer for protocol message."""
179 
180  def __init__(
181  self,
182  including_default_value_fields=False,
183  preserving_proto_field_name=False,
184  use_integers_for_enums=False,
185  descriptor_pool=None):
186  self.including_default_value_fields = including_default_value_fields
187  self.preserving_proto_field_name = preserving_proto_field_name
188  self.use_integers_for_enums = use_integers_for_enums
189  self.descriptor_pool = descriptor_pool
190 
191  def ToJsonString(self, message, indent, sort_keys):
192  js = self._MessageToJsonObject(message)
193  return json.dumps(js, indent=indent, sort_keys=sort_keys)
194 
195  def _MessageToJsonObject(self, message):
196  """Converts message to an object according to Proto3 JSON Specification."""
197  message_descriptor = message.DESCRIPTOR
198  full_name = message_descriptor.full_name
199  if _IsWrapperMessage(message_descriptor):
200  return self._WrapperMessageToJsonObject(message)
201  if full_name in _WKTJSONMETHODS:
202  return methodcaller(_WKTJSONMETHODS[full_name][0], message)(self)
203  js = {}
204  return self._RegularMessageToJsonObject(message, js)
205 
206  def _RegularMessageToJsonObject(self, message, js):
207  """Converts normal message according to Proto3 JSON Specification."""
208  fields = message.ListFields()
209 
210  try:
211  for field, value in fields:
213  name = field.name
214  else:
215  name = field.json_name
216  if _IsMapEntry(field):
217  # Convert a map field.
218  v_field = field.message_type.fields_by_name['value']
219  js_map = {}
220  for key in value:
221  if isinstance(key, bool):
222  if key:
223  recorded_key = 'true'
224  else:
225  recorded_key = 'false'
226  else:
227  recorded_key = key
228  js_map[recorded_key] = self._FieldToJsonObject(
229  v_field, value[key])
230  js[name] = js_map
231  elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
232  # Convert a repeated field.
233  js[name] = [self._FieldToJsonObject(field, k)
234  for k in value]
235  elif field.is_extension:
236  full_qualifier = field.full_name[:-len(field.name)]
237  name = '[%s%s]' % (full_qualifier, name)
238  js[name] = self._FieldToJsonObject(field, value)
239  else:
240  js[name] = self._FieldToJsonObject(field, value)
241 
242  # Serialize default value if including_default_value_fields is True.
244  message_descriptor = message.DESCRIPTOR
245  for field in message_descriptor.fields:
246  # Singular message fields and oneof fields will not be affected.
247  if ((field.label != descriptor.FieldDescriptor.LABEL_REPEATED and
248  field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE) or
249  field.containing_oneof):
250  continue
252  name = field.name
253  else:
254  name = field.json_name
255  if name in js:
256  # Skip the field which has been serailized already.
257  continue
258  if _IsMapEntry(field):
259  js[name] = {}
260  elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
261  js[name] = []
262  else:
263  js[name] = self._FieldToJsonObject(field, field.default_value)
264 
265  except ValueError as e:
266  raise SerializeToJsonError(
267  'Failed to serialize {0} field: {1}.'.format(field.name, e))
268 
269  return js
270 
271  def _FieldToJsonObject(self, field, value):
272  """Converts field value according to Proto3 JSON Specification."""
273  if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
274  return self._MessageToJsonObject(value)
275  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
276  if self.use_integers_for_enums:
277  return value
278  enum_value = field.enum_type.values_by_number.get(value, None)
279  if enum_value is not None:
280  return enum_value.name
281  else:
282  if field.file.syntax == 'proto3':
283  return value
284  raise SerializeToJsonError('Enum field contains an integer value '
285  'which can not mapped to an enum value.')
286  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
287  if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
288  # Use base64 Data encoding for bytes
289  return base64.b64encode(value).decode('utf-8')
290  else:
291  return value
292  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
293  return bool(value)
294  elif field.cpp_type in _INT64_TYPES:
295  return str(value)
296  elif field.cpp_type in _FLOAT_TYPES:
297  if math.isinf(value):
298  if value < 0.0:
299  return _NEG_INFINITY
300  else:
301  return _INFINITY
302  if math.isnan(value):
303  return _NAN
304  return value
305 
306  def _AnyMessageToJsonObject(self, message):
307  """Converts Any message according to Proto3 JSON Specification."""
308  if not message.ListFields():
309  return {}
310  # Must print @type first, use OrderedDict instead of {}
311  js = OrderedDict()
312  type_url = message.type_url
313  js['@type'] = type_url
314  sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool)
315  sub_message.ParseFromString(message.value)
316  message_descriptor = sub_message.DESCRIPTOR
317  full_name = message_descriptor.full_name
318  if _IsWrapperMessage(message_descriptor):
319  js['value'] = self._WrapperMessageToJsonObject(sub_message)
320  return js
321  if full_name in _WKTJSONMETHODS:
322  js['value'] = methodcaller(_WKTJSONMETHODS[full_name][0],
323  sub_message)(self)
324  return js
325  return self._RegularMessageToJsonObject(sub_message, js)
326 
327  def _GenericMessageToJsonObject(self, message):
328  """Converts message according to Proto3 JSON Specification."""
329  # Duration, Timestamp and FieldMask have ToJsonString method to do the
330  # convert. Users can also call the method directly.
331  return message.ToJsonString()
332 
333  def _ValueMessageToJsonObject(self, message):
334  """Converts Value message according to Proto3 JSON Specification."""
335  which = message.WhichOneof('kind')
336  # If the Value message is not set treat as null_value when serialize
337  # to JSON. The parse back result will be different from original message.
338  if which is None or which == 'null_value':
339  return None
340  if which == 'list_value':
341  return self._ListValueMessageToJsonObject(message.list_value)
342  if which == 'struct_value':
343  value = message.struct_value
344  else:
345  value = getattr(message, which)
346  oneof_descriptor = message.DESCRIPTOR.fields_by_name[which]
347  return self._FieldToJsonObject(oneof_descriptor, value)
348 
349  def _ListValueMessageToJsonObject(self, message):
350  """Converts ListValue message according to Proto3 JSON Specification."""
351  return [self._ValueMessageToJsonObject(value)
352  for value in message.values]
353 
354  def _StructMessageToJsonObject(self, message):
355  """Converts Struct message according to Proto3 JSON Specification."""
356  fields = message.fields
357  ret = {}
358  for key in fields:
359  ret[key] = self._ValueMessageToJsonObject(fields[key])
360  return ret
361 
362  def _WrapperMessageToJsonObject(self, message):
363  return self._FieldToJsonObject(
364  message.DESCRIPTOR.fields_by_name['value'], message.value)
365 
366 
367 def _IsWrapperMessage(message_descriptor):
368  return message_descriptor.file.name == 'google/protobuf/wrappers.proto'
369 
370 
372  result = {}
373  for name, value in js:
374  if name in result:
375  raise ParseError('Failed to load JSON: duplicate key {0}.'.format(name))
376  result[name] = value
377  return result
378 
379 
380 def _CreateMessageFromTypeUrl(type_url, descriptor_pool):
381  """Creates a message from a type URL."""
382  db = symbol_database.Default()
383  pool = db.pool if descriptor_pool is None else descriptor_pool
384  type_name = type_url.split('/')[-1]
385  try:
386  message_descriptor = pool.FindMessageTypeByName(type_name)
387  except KeyError:
388  raise TypeError(
389  'Can not find message descriptor by type_url: {0}.'.format(type_url))
390  message_class = db.GetPrototype(message_descriptor)
391  return message_class()
392 
393 
394 def Parse(text, message, ignore_unknown_fields=False, descriptor_pool=None):
395  """Parses a JSON representation of a protocol message into a message.
396 
397  Args:
398  text: Message JSON representation.
399  message: A protocol buffer message to merge into.
400  ignore_unknown_fields: If True, do not raise errors for unknown fields.
401  descriptor_pool: A Descriptor Pool for resolving types. If None use the
402  default.
403 
404  Returns:
405  The same message passed as argument.
406 
407  Raises::
408  ParseError: On JSON parsing problems.
409  """
410  if not isinstance(text, six.text_type): text = text.decode('utf-8')
411  try:
412  js = json.loads(text, object_pairs_hook=_DuplicateChecker)
413  except ValueError as e:
414  raise ParseError('Failed to load JSON: {0}.'.format(str(e)))
415  return ParseDict(js, message, ignore_unknown_fields, descriptor_pool)
416 
417 
418 def ParseDict(js_dict,
419  message,
420  ignore_unknown_fields=False,
421  descriptor_pool=None):
422  """Parses a JSON dictionary representation into a message.
423 
424  Args:
425  js_dict: Dict representation of a JSON message.
426  message: A protocol buffer message to merge into.
427  ignore_unknown_fields: If True, do not raise errors for unknown fields.
428  descriptor_pool: A Descriptor Pool for resolving types. If None use the
429  default.
430 
431  Returns:
432  The same message passed as argument.
433  """
434  parser = _Parser(ignore_unknown_fields, descriptor_pool)
435  parser.ConvertMessage(js_dict, message)
436  return message
437 
438 
439 _INT_OR_FLOAT = six.integer_types + (float,)
440 
441 
442 class _Parser(object):
443  """JSON format parser for protocol message."""
444 
445  def __init__(self, ignore_unknown_fields, descriptor_pool):
446  self.ignore_unknown_fields = ignore_unknown_fields
447  self.descriptor_pool = descriptor_pool
448 
449  def ConvertMessage(self, value, message):
450  """Convert a JSON object into a message.
451 
452  Args:
453  value: A JSON object.
454  message: A WKT or regular protocol message to record the data.
455 
456  Raises:
457  ParseError: In case of convert problems.
458  """
459  message_descriptor = message.DESCRIPTOR
460  full_name = message_descriptor.full_name
461  if _IsWrapperMessage(message_descriptor):
462  self._ConvertWrapperMessage(value, message)
463  elif full_name in _WKTJSONMETHODS:
464  methodcaller(_WKTJSONMETHODS[full_name][1], value, message)(self)
465  else:
466  self._ConvertFieldValuePair(value, message)
467 
468  def _ConvertFieldValuePair(self, js, message):
469  """Convert field value pairs into regular message.
470 
471  Args:
472  js: A JSON object to convert the field value pairs.
473  message: A regular protocol message to record the data.
474 
475  Raises:
476  ParseError: In case of problems converting.
477  """
478  names = []
479  message_descriptor = message.DESCRIPTOR
480  fields_by_json_name = dict((f.json_name, f)
481  for f in message_descriptor.fields)
482  for name in js:
483  try:
484  field = fields_by_json_name.get(name, None)
485  if not field:
486  field = message_descriptor.fields_by_name.get(name, None)
487  if not field and _VALID_EXTENSION_NAME.match(name):
488  if not message_descriptor.is_extendable:
489  raise ParseError('Message type {0} does not have extensions'.format(
490  message_descriptor.full_name))
491  identifier = name[1:-1] # strip [] brackets
492  # pylint: disable=protected-access
493  field = message.Extensions._FindExtensionByName(identifier)
494  # pylint: enable=protected-access
495  if not field:
496  # Try looking for extension by the message type name, dropping the
497  # field name following the final . separator in full_name.
498  identifier = '.'.join(identifier.split('.')[:-1])
499  # pylint: disable=protected-access
500  field = message.Extensions._FindExtensionByName(identifier)
501  # pylint: enable=protected-access
502  if not field:
503  if self.ignore_unknown_fields:
504  continue
505  raise ParseError(
506  ('Message type "{0}" has no field named "{1}".\n'
507  ' Available Fields(except extensions): {2}').format(
508  message_descriptor.full_name, name,
509  [f.json_name for f in message_descriptor.fields]))
510  if name in names:
511  raise ParseError('Message type "{0}" should not have multiple '
512  '"{1}" fields.'.format(
513  message.DESCRIPTOR.full_name, name))
514  names.append(name)
515  # Check no other oneof field is parsed.
516  if field.containing_oneof is not None:
517  oneof_name = field.containing_oneof.name
518  if oneof_name in names:
519  raise ParseError('Message type "{0}" should not have multiple '
520  '"{1}" oneof fields.'.format(
521  message.DESCRIPTOR.full_name, oneof_name))
522  names.append(oneof_name)
523 
524  value = js[name]
525  if value is None:
526  if (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE
527  and field.message_type.full_name == 'google.protobuf.Value'):
528  sub_message = getattr(message, field.name)
529  sub_message.null_value = 0
530  else:
531  message.ClearField(field.name)
532  continue
533 
534  # Parse field value.
535  if _IsMapEntry(field):
536  message.ClearField(field.name)
537  self._ConvertMapFieldValue(value, message, field)
538  elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
539  message.ClearField(field.name)
540  if not isinstance(value, list):
541  raise ParseError('repeated field {0} must be in [] which is '
542  '{1}.'.format(name, value))
543  if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
544  # Repeated message field.
545  for item in value:
546  sub_message = getattr(message, field.name).add()
547  # None is a null_value in Value.
548  if (item is None and
549  sub_message.DESCRIPTOR.full_name != 'google.protobuf.Value'):
550  raise ParseError('null is not allowed to be used as an element'
551  ' in a repeated field.')
552  self.ConvertMessage(item, sub_message)
553  else:
554  # Repeated scalar field.
555  for item in value:
556  if item is None:
557  raise ParseError('null is not allowed to be used as an element'
558  ' in a repeated field.')
559  getattr(message, field.name).append(
560  _ConvertScalarFieldValue(item, field))
561  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
562  if field.is_extension:
563  sub_message = message.Extensions[field]
564  else:
565  sub_message = getattr(message, field.name)
566  sub_message.SetInParent()
567  self.ConvertMessage(value, sub_message)
568  else:
569  if field.is_extension:
570  message.Extensions[field] = _ConvertScalarFieldValue(value, field)
571  else:
572  setattr(message, field.name, _ConvertScalarFieldValue(value, field))
573  except ParseError as e:
574  if field and field.containing_oneof is None:
575  raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
576  else:
577  raise ParseError(str(e))
578  except ValueError as e:
579  raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
580  except TypeError as e:
581  raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
582 
583  def _ConvertAnyMessage(self, value, message):
584  """Convert a JSON representation into Any message."""
585  if isinstance(value, dict) and not value:
586  return
587  try:
588  type_url = value['@type']
589  except KeyError:
590  raise ParseError('@type is missing when parsing any message.')
591 
592  sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool)
593  message_descriptor = sub_message.DESCRIPTOR
594  full_name = message_descriptor.full_name
595  if _IsWrapperMessage(message_descriptor):
596  self._ConvertWrapperMessage(value['value'], sub_message)
597  elif full_name in _WKTJSONMETHODS:
598  methodcaller(
599  _WKTJSONMETHODS[full_name][1], value['value'], sub_message)(self)
600  else:
601  del value['@type']
602  self._ConvertFieldValuePair(value, sub_message)
603  value['@type'] = type_url
604  # Sets Any message
605  message.value = sub_message.SerializeToString()
606  message.type_url = type_url
607 
608  def _ConvertGenericMessage(self, value, message):
609  """Convert a JSON representation into message with FromJsonString."""
610  # Duration, Timestamp, FieldMask have a FromJsonString method to do the
611  # conversion. Users can also call the method directly.
612  try:
613  message.FromJsonString(value)
614  except ValueError as e:
615  raise ParseError(e)
616 
617  def _ConvertValueMessage(self, value, message):
618  """Convert a JSON representation into Value message."""
619  if isinstance(value, dict):
620  self._ConvertStructMessage(value, message.struct_value)
621  elif isinstance(value, list):
622  self. _ConvertListValueMessage(value, message.list_value)
623  elif value is None:
624  message.null_value = 0
625  elif isinstance(value, bool):
626  message.bool_value = value
627  elif isinstance(value, six.string_types):
628  message.string_value = value
629  elif isinstance(value, _INT_OR_FLOAT):
630  message.number_value = value
631  else:
632  raise ParseError('Unexpected type for Value message.')
633 
634  def _ConvertListValueMessage(self, value, message):
635  """Convert a JSON representation into ListValue message."""
636  if not isinstance(value, list):
637  raise ParseError(
638  'ListValue must be in [] which is {0}.'.format(value))
639  message.ClearField('values')
640  for item in value:
641  self._ConvertValueMessage(item, message.values.add())
642 
643  def _ConvertStructMessage(self, value, message):
644  """Convert a JSON representation into Struct message."""
645  if not isinstance(value, dict):
646  raise ParseError(
647  'Struct must be in a dict which is {0}.'.format(value))
648  # Clear will mark the struct as modified so it will be created even if
649  # there are no values.
650  message.Clear()
651  for key in value:
652  self._ConvertValueMessage(value[key], message.fields[key])
653  return
654 
655  def _ConvertWrapperMessage(self, value, message):
656  """Convert a JSON representation into Wrapper message."""
657  field = message.DESCRIPTOR.fields_by_name['value']
658  setattr(message, 'value', _ConvertScalarFieldValue(value, field))
659 
660  def _ConvertMapFieldValue(self, value, message, field):
661  """Convert map field value for a message map field.
662 
663  Args:
664  value: A JSON object to convert the map field value.
665  message: A protocol message to record the converted data.
666  field: The descriptor of the map field to be converted.
667 
668  Raises:
669  ParseError: In case of convert problems.
670  """
671  if not isinstance(value, dict):
672  raise ParseError(
673  'Map field {0} must be in a dict which is {1}.'.format(
674  field.name, value))
675  key_field = field.message_type.fields_by_name['key']
676  value_field = field.message_type.fields_by_name['value']
677  for key in value:
678  key_value = _ConvertScalarFieldValue(key, key_field, True)
679  if value_field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
680  self.ConvertMessage(value[key], getattr(
681  message, field.name)[key_value])
682  else:
683  getattr(message, field.name)[key_value] = _ConvertScalarFieldValue(
684  value[key], value_field)
685 
686 
687 def _ConvertScalarFieldValue(value, field, require_str=False):
688  """Convert a single scalar field value.
689 
690  Args:
691  value: A scalar value to convert the scalar field value.
692  field: The descriptor of the field to convert.
693  require_str: If True, the field value must be a str.
694 
695  Returns:
696  The converted scalar field value
697 
698  Raises:
699  ParseError: In case of convert problems.
700  """
701  if field.cpp_type in _INT_TYPES:
702  return _ConvertInteger(value)
703  elif field.cpp_type in _FLOAT_TYPES:
704  return _ConvertFloat(value)
705  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
706  return _ConvertBool(value, require_str)
707  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
708  if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
709  return base64.b64decode(value)
710  else:
711  # Checking for unpaired surrogates appears to be unreliable,
712  # depending on the specific Python version, so we check manually.
713  if _UNPAIRED_SURROGATE_PATTERN.search(value):
714  raise ParseError('Unpaired surrogate')
715  return value
716  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
717  # Convert an enum value.
718  enum_value = field.enum_type.values_by_name.get(value, None)
719  if enum_value is None:
720  try:
721  number = int(value)
722  enum_value = field.enum_type.values_by_number.get(number, None)
723  except ValueError:
724  raise ParseError('Invalid enum value {0} for enum type {1}.'.format(
725  value, field.enum_type.full_name))
726  if enum_value is None:
727  if field.file.syntax == 'proto3':
728  # Proto3 accepts unknown enums.
729  return number
730  raise ParseError('Invalid enum value {0} for enum type {1}.'.format(
731  value, field.enum_type.full_name))
732  return enum_value.number
733 
734 
735 def _ConvertInteger(value):
736  """Convert an integer.
737 
738  Args:
739  value: A scalar value to convert.
740 
741  Returns:
742  The integer value.
743 
744  Raises:
745  ParseError: If an integer couldn't be consumed.
746  """
747  if isinstance(value, float) and not value.is_integer():
748  raise ParseError('Couldn\'t parse integer: {0}.'.format(value))
749 
750  if isinstance(value, six.text_type) and value.find(' ') != -1:
751  raise ParseError('Couldn\'t parse integer: "{0}".'.format(value))
752 
753  return int(value)
754 
755 
756 def _ConvertFloat(value):
757  """Convert an floating point number."""
758  if value == 'nan':
759  raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.')
760  try:
761  # Assume Python compatible syntax.
762  return float(value)
763  except ValueError:
764  # Check alternative spellings.
765  if value == _NEG_INFINITY:
766  return float('-inf')
767  elif value == _INFINITY:
768  return float('inf')
769  elif value == _NAN:
770  return float('nan')
771  else:
772  raise ParseError('Couldn\'t parse float: {0}.'.format(value))
773 
774 
775 def _ConvertBool(value, require_str):
776  """Convert a boolean value.
777 
778  Args:
779  value: A scalar value to convert.
780  require_str: If True, value must be a str.
781 
782  Returns:
783  The bool parsed.
784 
785  Raises:
786  ParseError: If a boolean value couldn't be consumed.
787  """
788  if require_str:
789  if value == 'true':
790  return True
791  elif value == 'false':
792  return False
793  else:
794  raise ParseError('Expected "true" or "false", not {0}.'.format(value))
795 
796  if not isinstance(value, bool):
797  raise ParseError('Expected true or false without quotes.')
798  return value
799 
800 _WKTJSONMETHODS = {
801  'google.protobuf.Any': ['_AnyMessageToJsonObject',
802  '_ConvertAnyMessage'],
803  'google.protobuf.Duration': ['_GenericMessageToJsonObject',
804  '_ConvertGenericMessage'],
805  'google.protobuf.FieldMask': ['_GenericMessageToJsonObject',
806  '_ConvertGenericMessage'],
807  'google.protobuf.ListValue': ['_ListValueMessageToJsonObject',
808  '_ConvertListValueMessage'],
809  'google.protobuf.Struct': ['_StructMessageToJsonObject',
810  '_ConvertStructMessage'],
811  'google.protobuf.Timestamp': ['_GenericMessageToJsonObject',
812  '_ConvertGenericMessage'],
813  'google.protobuf.Value': ['_ValueMessageToJsonObject',
814  '_ConvertValueMessage']
815 }
google::protobuf.json_format._Parser.descriptor_pool
descriptor_pool
Definition: json_format.py:447
google::protobuf.json_format._Printer._MessageToJsonObject
def _MessageToJsonObject(self, message)
Definition: json_format.py:195
google::protobuf.json_format._Printer._StructMessageToJsonObject
def _StructMessageToJsonObject(self, message)
Definition: json_format.py:354
google::protobuf.json_format._IsWrapperMessage
def _IsWrapperMessage(message_descriptor)
Definition: json_format.py:367
getattr
static uint64_t getattr(const tarjan *t, const upb_refcounted *r)
Definition: ruby/ext/google/protobuf_c/upb.c:5868
google::protobuf.json_format._Printer.including_default_value_fields
including_default_value_fields
Definition: json_format.py:181
google::protobuf.json_format._Printer.ToJsonString
def ToJsonString(self, message, indent, sort_keys)
Definition: json_format.py:191
google::protobuf.json_format.MessageToDict
def MessageToDict(message, including_default_value_fields=False, preserving_proto_field_name=False, use_integers_for_enums=False, descriptor_pool=None)
Definition: json_format.py:136
google::protobuf.json_format._Printer._AnyMessageToJsonObject
def _AnyMessageToJsonObject(self, message)
Definition: json_format.py:306
google::protobuf.json_format._Parser._ConvertValueMessage
def _ConvertValueMessage(self, value, message)
Definition: json_format.py:617
google::protobuf
Definition: data_proto2_to_proto3_util.h:12
setattr
static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr)
Definition: ruby/ext/google/protobuf_c/upb.c:5875
google::protobuf.json_format.SerializeToJsonError
Definition: json_format.py:91
google::protobuf.json_format._Parser.ConvertMessage
def ConvertMessage(self, value, message)
Definition: json_format.py:449
google::protobuf.json_format._Printer._GenericMessageToJsonObject
def _GenericMessageToJsonObject(self, message)
Definition: json_format.py:327
google::protobuf.json_format._Printer._FieldToJsonObject
def _FieldToJsonObject(self, field, value)
Definition: json_format.py:271
google::protobuf.json_format._ConvertInteger
def _ConvertInteger(value)
Definition: json_format.py:735
google::protobuf.json_format._Parser._ConvertGenericMessage
def _ConvertGenericMessage(self, value, message)
Definition: json_format.py:608
google::protobuf.json_format._Printer._ValueMessageToJsonObject
def _ValueMessageToJsonObject(self, message)
Definition: json_format.py:333
google::protobuf.json_format._Printer._ListValueMessageToJsonObject
def _ListValueMessageToJsonObject(self, message)
Definition: json_format.py:349
google::protobuf.json_format._CreateMessageFromTypeUrl
def _CreateMessageFromTypeUrl(type_url, descriptor_pool)
Definition: json_format.py:380
update_failure_list.str
str
Definition: update_failure_list.py:41
google::protobuf.json_format._Printer.__init__
def __init__(self, including_default_value_fields=False, preserving_proto_field_name=False, use_integers_for_enums=False, descriptor_pool=None)
Definition: json_format.py:180
google::protobuf.json_format._ConvertScalarFieldValue
def _ConvertScalarFieldValue(value, field, require_str=False)
Definition: json_format.py:687
google::protobuf.json_format._Parser._ConvertFieldValuePair
def _ConvertFieldValuePair(self, js, message)
Definition: json_format.py:468
google::protobuf.json_format._Parser
Definition: json_format.py:442
google::protobuf.json_format._Parser._ConvertListValueMessage
def _ConvertListValueMessage(self, value, message)
Definition: json_format.py:634
google::protobuf.json_format._IsMapEntry
def _IsMapEntry(field)
Definition: json_format.py:171
google::protobuf.json_format._Printer
Definition: json_format.py:177
google::protobuf.json_format._Printer.descriptor_pool
descriptor_pool
Definition: json_format.py:184
google::protobuf.json_format._Printer._RegularMessageToJsonObject
def _RegularMessageToJsonObject(self, message, js)
Definition: json_format.py:206
google::protobuf.json_format._ConvertFloat
def _ConvertFloat(value)
Definition: json_format.py:756
google::protobuf.json_format._Parser._ConvertAnyMessage
def _ConvertAnyMessage(self, value, message)
Definition: json_format.py:583
google::protobuf.json_format._Printer._WrapperMessageToJsonObject
def _WrapperMessageToJsonObject(self, message)
Definition: json_format.py:362
google::protobuf.json_format.ParseDict
def ParseDict(js_dict, message, ignore_unknown_fields=False, descriptor_pool=None)
Definition: json_format.py:418
google::protobuf.json_format.MessageToJson
def MessageToJson(message, including_default_value_fields=False, preserving_proto_field_name=False, indent=2, sort_keys=False, use_integers_for_enums=False, descriptor_pool=None)
Definition: json_format.py:99
google::protobuf.json_format.Parse
def Parse(text, message, ignore_unknown_fields=False, descriptor_pool=None)
Definition: json_format.py:394
len
int len
Definition: php/ext/google/protobuf/map.c:206
google::protobuf.json_format._Parser._ConvertWrapperMessage
def _ConvertWrapperMessage(self, value, message)
Definition: json_format.py:655
google::protobuf.json_format.Error
Definition: json_format.py:87
google::protobuf.json_format._Printer.preserving_proto_field_name
preserving_proto_field_name
Definition: json_format.py:182
google::protobuf.json_format._Parser._ConvertStructMessage
def _ConvertStructMessage(self, value, message)
Definition: json_format.py:643
google::protobuf.json_format._DuplicateChecker
def _DuplicateChecker(js)
Definition: json_format.py:371
google::protobuf.json_format._Printer.use_integers_for_enums
use_integers_for_enums
Definition: json_format.py:183
google::protobuf.json_format.ParseError
Definition: json_format.py:95
google::protobuf.json_format._Parser._ConvertMapFieldValue
def _ConvertMapFieldValue(self, value, message, field)
Definition: json_format.py:660
google::protobuf.json_format._ConvertBool
def _ConvertBool(value, require_str)
Definition: json_format.py:775
google::protobuf.json_format._Parser.__init__
def __init__(self, ignore_unknown_fields, descriptor_pool)
Definition: json_format.py:445
google::protobuf.json_format._Parser.ignore_unknown_fields
ignore_unknown_fields
Definition: json_format.py:446


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:55