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


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:25