Package google :: Package protobuf :: Module json_format
[frames] | no frames]

Source Code for Module google.protobuf.json_format

  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  try: 
 46      from collections import OrderedDict 
 47  except ImportError: 
 48      from ordereddict import OrderedDict  #PY26 
 49  import base64 
 50  import json 
 51  import math 
 52  import re 
 53  import six 
 54  import sys 
 55   
 56  from operator import methodcaller 
 57  from google.protobuf import descriptor 
 58  from google.protobuf import symbol_database 
 59   
 60  _TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' 
 61  _INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32, 
 62                          descriptor.FieldDescriptor.CPPTYPE_UINT32, 
 63                          descriptor.FieldDescriptor.CPPTYPE_INT64, 
 64                          descriptor.FieldDescriptor.CPPTYPE_UINT64]) 
 65  _INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64, 
 66                            descriptor.FieldDescriptor.CPPTYPE_UINT64]) 
 67  _FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, 
 68                            descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) 
 69  _INFINITY = 'Infinity' 
 70  _NEG_INFINITY = '-Infinity' 
 71  _NAN = 'NaN' 
 72   
 73  _UNPAIRED_SURROGATE_PATTERN = re.compile(six.u( 
 74      r'[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]' 
 75  )) 
 76   
77 -class Error(Exception):
78 """Top-level module error for json_format."""
79 80
81 -class SerializeToJsonError(Error):
82 """Thrown if serialization to JSON fails."""
83 84
85 -class ParseError(Error):
86 """Thrown in case of parsing error."""
87 88
89 -def MessageToJson(message, including_default_value_fields=False):
90 """Converts protobuf message to JSON format. 91 92 Args: 93 message: The protocol buffers message instance to serialize. 94 including_default_value_fields: If True, singular primitive fields, 95 repeated fields, and map fields will always be serialized. If 96 False, only serialize non-empty fields. Singular message fields 97 and oneof fields are not affected by this option. 98 99 Returns: 100 A string containing the JSON formatted protocol buffer message. 101 """ 102 printer = _Printer(including_default_value_fields) 103 return printer.ToJsonString(message)
104 105
106 -def _IsMapEntry(field):
107 return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and 108 field.message_type.has_options and 109 field.message_type.GetOptions().map_entry)
110 111
112 -class _Printer(object):
113 """JSON format printer for protocol message.""" 114
115 - def __init__(self, 116 including_default_value_fields=False):
117 self.including_default_value_fields = including_default_value_fields
118
119 - def ToJsonString(self, message):
120 js = self._MessageToJsonObject(message) 121 return json.dumps(js, indent=2)
122
123 - def _MessageToJsonObject(self, message):
124 """Converts message to an object according to Proto3 JSON Specification.""" 125 message_descriptor = message.DESCRIPTOR 126 full_name = message_descriptor.full_name 127 if _IsWrapperMessage(message_descriptor): 128 return self._WrapperMessageToJsonObject(message) 129 if full_name in _WKTJSONMETHODS: 130 return methodcaller(_WKTJSONMETHODS[full_name][0], message)(self) 131 js = {} 132 return self._RegularMessageToJsonObject(message, js)
133
134 - def _RegularMessageToJsonObject(self, message, js):
135 """Converts normal message according to Proto3 JSON Specification.""" 136 fields = message.ListFields() 137 138 try: 139 for field, value in fields: 140 name = field.camelcase_name 141 if _IsMapEntry(field): 142 # Convert a map field. 143 v_field = field.message_type.fields_by_name['value'] 144 js_map = {} 145 for key in value: 146 if isinstance(key, bool): 147 if key: 148 recorded_key = 'true' 149 else: 150 recorded_key = 'false' 151 else: 152 recorded_key = key 153 js_map[recorded_key] = self._FieldToJsonObject( 154 v_field, value[key]) 155 js[name] = js_map 156 elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 157 # Convert a repeated field. 158 js[name] = [self._FieldToJsonObject(field, k) 159 for k in value] 160 else: 161 js[name] = self._FieldToJsonObject(field, value) 162 163 # Serialize default value if including_default_value_fields is True. 164 if self.including_default_value_fields: 165 message_descriptor = message.DESCRIPTOR 166 for field in message_descriptor.fields: 167 # Singular message fields and oneof fields will not be affected. 168 if ((field.label != descriptor.FieldDescriptor.LABEL_REPEATED and 169 field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE) or 170 field.containing_oneof): 171 continue 172 name = field.camelcase_name 173 if name in js: 174 # Skip the field which has been serailized already. 175 continue 176 if _IsMapEntry(field): 177 js[name] = {} 178 elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 179 js[name] = [] 180 else: 181 js[name] = self._FieldToJsonObject(field, field.default_value) 182 183 except ValueError as e: 184 raise SerializeToJsonError( 185 'Failed to serialize {0} field: {1}.'.format(field.name, e)) 186 187 return js
188
189 - def _FieldToJsonObject(self, field, value):
190 """Converts field value according to Proto3 JSON Specification.""" 191 if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 192 return self._MessageToJsonObject(value) 193 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: 194 enum_value = field.enum_type.values_by_number.get(value, None) 195 if enum_value is not None: 196 return enum_value.name 197 else: 198 raise SerializeToJsonError('Enum field contains an integer value ' 199 'which can not mapped to an enum value.') 200 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: 201 if field.type == descriptor.FieldDescriptor.TYPE_BYTES: 202 # Use base64 Data encoding for bytes 203 return base64.b64encode(value).decode('utf-8') 204 else: 205 return value 206 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: 207 return bool(value) 208 elif field.cpp_type in _INT64_TYPES: 209 return str(value) 210 elif field.cpp_type in _FLOAT_TYPES: 211 if math.isinf(value): 212 if value < 0.0: 213 return _NEG_INFINITY 214 else: 215 return _INFINITY 216 if math.isnan(value): 217 return _NAN 218 return value
219
220 - def _AnyMessageToJsonObject(self, message):
221 """Converts Any message according to Proto3 JSON Specification.""" 222 if not message.ListFields(): 223 return {} 224 # Must print @type first, use OrderedDict instead of {} 225 js = OrderedDict() 226 type_url = message.type_url 227 js['@type'] = type_url 228 sub_message = _CreateMessageFromTypeUrl(type_url) 229 sub_message.ParseFromString(message.value) 230 message_descriptor = sub_message.DESCRIPTOR 231 full_name = message_descriptor.full_name 232 if _IsWrapperMessage(message_descriptor): 233 js['value'] = self._WrapperMessageToJsonObject(sub_message) 234 return js 235 if full_name in _WKTJSONMETHODS: 236 js['value'] = methodcaller(_WKTJSONMETHODS[full_name][0], 237 sub_message)(self) 238 return js 239 return self._RegularMessageToJsonObject(sub_message, js)
240
241 - def _GenericMessageToJsonObject(self, message):
242 """Converts message according to Proto3 JSON Specification.""" 243 # Duration, Timestamp and FieldMask have ToJsonString method to do the 244 # convert. Users can also call the method directly. 245 return message.ToJsonString()
246
247 - def _ValueMessageToJsonObject(self, message):
248 """Converts Value message according to Proto3 JSON Specification.""" 249 which = message.WhichOneof('kind') 250 # If the Value message is not set treat as null_value when serialize 251 # to JSON. The parse back result will be different from original message. 252 if which is None or which == 'null_value': 253 return None 254 if which == 'list_value': 255 return self._ListValueMessageToJsonObject(message.list_value) 256 if which == 'struct_value': 257 value = message.struct_value 258 else: 259 value = getattr(message, which) 260 oneof_descriptor = message.DESCRIPTOR.fields_by_name[which] 261 return self._FieldToJsonObject(oneof_descriptor, value)
262
263 - def _ListValueMessageToJsonObject(self, message):
264 """Converts ListValue message according to Proto3 JSON Specification.""" 265 return [self._ValueMessageToJsonObject(value) 266 for value in message.values]
267
268 - def _StructMessageToJsonObject(self, message):
269 """Converts Struct message according to Proto3 JSON Specification.""" 270 fields = message.fields 271 ret = {} 272 for key in fields: 273 ret[key] = self._ValueMessageToJsonObject(fields[key]) 274 return ret
275
276 - def _WrapperMessageToJsonObject(self, message):
277 return self._FieldToJsonObject( 278 message.DESCRIPTOR.fields_by_name['value'], message.value)
279 280
281 -def _IsWrapperMessage(message_descriptor):
282 return message_descriptor.file.name == 'google/protobuf/wrappers.proto'
283 284
285 -def _DuplicateChecker(js):
286 result = {} 287 for name, value in js: 288 if name in result: 289 raise ParseError('Failed to load JSON: duplicate key {0}.'.format(name)) 290 result[name] = value 291 return result
292 293
294 -def _CreateMessageFromTypeUrl(type_url):
295 # TODO(jieluo): Should add a way that users can register the type resolver 296 # instead of the default one. 297 db = symbol_database.Default() 298 type_name = type_url.split('/')[-1] 299 try: 300 message_descriptor = db.pool.FindMessageTypeByName(type_name) 301 except KeyError: 302 raise TypeError( 303 'Can not find message descriptor by type_url: {0}.'.format(type_url)) 304 message_class = db.GetPrototype(message_descriptor) 305 return message_class()
306 307
308 -def Parse(text, message, ignore_unknown_fields=False):
309 """Parses a JSON representation of a protocol message into a message. 310 311 Args: 312 text: Message JSON representation. 313 message: A protocol beffer message to merge into. 314 ignore_unknown_fields: If True, do not raise errors for unknown fields. 315 316 Returns: 317 The same message passed as argument. 318 319 Raises:: 320 ParseError: On JSON parsing problems. 321 """ 322 if not isinstance(text, six.text_type): text = text.decode('utf-8') 323 try: 324 if sys.version_info < (2, 7): 325 # object_pair_hook is not supported before python2.7 326 js = json.loads(text) 327 else: 328 js = json.loads(text, object_pairs_hook=_DuplicateChecker) 329 except ValueError as e: 330 raise ParseError('Failed to load JSON: {0}.'.format(str(e))) 331 parser = _Parser(ignore_unknown_fields) 332 parser.ConvertMessage(js, message) 333 return message
334 335 336 _INT_OR_FLOAT = six.integer_types + (float,) 337 338
339 -class _Parser(object):
340 """JSON format parser for protocol message.""" 341
342 - def __init__(self, 343 ignore_unknown_fields):
344 self.ignore_unknown_fields = ignore_unknown_fields
345
346 - def ConvertMessage(self, value, message):
347 """Convert a JSON object into a message. 348 349 Args: 350 value: A JSON object. 351 message: A WKT or regular protocol message to record the data. 352 353 Raises: 354 ParseError: In case of convert problems. 355 """ 356 message_descriptor = message.DESCRIPTOR 357 full_name = message_descriptor.full_name 358 if _IsWrapperMessage(message_descriptor): 359 self._ConvertWrapperMessage(value, message) 360 elif full_name in _WKTJSONMETHODS: 361 methodcaller(_WKTJSONMETHODS[full_name][1], value, message)(self) 362 else: 363 self._ConvertFieldValuePair(value, message)
364
365 - def _ConvertFieldValuePair(self, js, message):
366 """Convert field value pairs into regular message. 367 368 Args: 369 js: A JSON object to convert the field value pairs. 370 message: A regular protocol message to record the data. 371 372 Raises: 373 ParseError: In case of problems converting. 374 """ 375 names = [] 376 message_descriptor = message.DESCRIPTOR 377 for name in js: 378 try: 379 field = message_descriptor.fields_by_camelcase_name.get(name, None) 380 if not field: 381 if self.ignore_unknown_fields: 382 continue 383 raise ParseError( 384 'Message type "{0}" has no field named "{1}".'.format( 385 message_descriptor.full_name, name)) 386 if name in names: 387 raise ParseError('Message type "{0}" should not have multiple ' 388 '"{1}" fields.'.format( 389 message.DESCRIPTOR.full_name, name)) 390 names.append(name) 391 # Check no other oneof field is parsed. 392 if field.containing_oneof is not None: 393 oneof_name = field.containing_oneof.name 394 if oneof_name in names: 395 raise ParseError('Message type "{0}" should not have multiple ' 396 '"{1}" oneof fields.'.format( 397 message.DESCRIPTOR.full_name, oneof_name)) 398 names.append(oneof_name) 399 400 value = js[name] 401 if value is None: 402 message.ClearField(field.name) 403 continue 404 405 # Parse field value. 406 if _IsMapEntry(field): 407 message.ClearField(field.name) 408 self._ConvertMapFieldValue(value, message, field) 409 elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 410 message.ClearField(field.name) 411 if not isinstance(value, list): 412 raise ParseError('repeated field {0} must be in [] which is ' 413 '{1}.'.format(name, value)) 414 if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 415 # Repeated message field. 416 for item in value: 417 sub_message = getattr(message, field.name).add() 418 # None is a null_value in Value. 419 if (item is None and 420 sub_message.DESCRIPTOR.full_name != 'google.protobuf.Value'): 421 raise ParseError('null is not allowed to be used as an element' 422 ' in a repeated field.') 423 self.ConvertMessage(item, sub_message) 424 else: 425 # Repeated scalar field. 426 for item in value: 427 if item is None: 428 raise ParseError('null is not allowed to be used as an element' 429 ' in a repeated field.') 430 getattr(message, field.name).append( 431 _ConvertScalarFieldValue(item, field)) 432 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 433 sub_message = getattr(message, field.name) 434 self.ConvertMessage(value, sub_message) 435 else: 436 setattr(message, field.name, _ConvertScalarFieldValue(value, field)) 437 except ParseError as e: 438 if field and field.containing_oneof is None: 439 raise ParseError('Failed to parse {0} field: {1}'.format(name, e)) 440 else: 441 raise ParseError(str(e)) 442 except ValueError as e: 443 raise ParseError('Failed to parse {0} field: {1}.'.format(name, e)) 444 except TypeError as e: 445 raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
446
447 - def _ConvertAnyMessage(self, value, message):
448 """Convert a JSON representation into Any message.""" 449 if isinstance(value, dict) and not value: 450 return 451 try: 452 type_url = value['@type'] 453 except KeyError: 454 raise ParseError('@type is missing when parsing any message.') 455 456 sub_message = _CreateMessageFromTypeUrl(type_url) 457 message_descriptor = sub_message.DESCRIPTOR 458 full_name = message_descriptor.full_name 459 if _IsWrapperMessage(message_descriptor): 460 self._ConvertWrapperMessage(value['value'], sub_message) 461 elif full_name in _WKTJSONMETHODS: 462 methodcaller( 463 _WKTJSONMETHODS[full_name][1], value['value'], sub_message)(self) 464 else: 465 del value['@type'] 466 self._ConvertFieldValuePair(value, sub_message) 467 # Sets Any message 468 message.value = sub_message.SerializeToString() 469 message.type_url = type_url
470
471 - def _ConvertGenericMessage(self, value, message):
472 """Convert a JSON representation into message with FromJsonString.""" 473 # Durantion, Timestamp, FieldMask have FromJsonString method to do the 474 # convert. Users can also call the method directly. 475 message.FromJsonString(value)
476
477 - def _ConvertValueMessage(self, value, message):
478 """Convert a JSON representation into Value message.""" 479 if isinstance(value, dict): 480 self._ConvertStructMessage(value, message.struct_value) 481 elif isinstance(value, list): 482 self. _ConvertListValueMessage(value, message.list_value) 483 elif value is None: 484 message.null_value = 0 485 elif isinstance(value, bool): 486 message.bool_value = value 487 elif isinstance(value, six.string_types): 488 message.string_value = value 489 elif isinstance(value, _INT_OR_FLOAT): 490 message.number_value = value 491 else: 492 raise ParseError('Unexpected type for Value message.')
493
494 - def _ConvertListValueMessage(self, value, message):
495 """Convert a JSON representation into ListValue message.""" 496 if not isinstance(value, list): 497 raise ParseError( 498 'ListValue must be in [] which is {0}.'.format(value)) 499 message.ClearField('values') 500 for item in value: 501 self._ConvertValueMessage(item, message.values.add())
502
503 - def _ConvertStructMessage(self, value, message):
504 """Convert a JSON representation into Struct message.""" 505 if not isinstance(value, dict): 506 raise ParseError( 507 'Struct must be in a dict which is {0}.'.format(value)) 508 for key in value: 509 self._ConvertValueMessage(value[key], message.fields[key]) 510 return
511
512 - def _ConvertWrapperMessage(self, value, message):
513 """Convert a JSON representation into Wrapper message.""" 514 field = message.DESCRIPTOR.fields_by_name['value'] 515 setattr(message, 'value', _ConvertScalarFieldValue(value, field))
516
517 - def _ConvertMapFieldValue(self, value, message, field):
518 """Convert map field value for a message map field. 519 520 Args: 521 value: A JSON object to convert the map field value. 522 message: A protocol message to record the converted data. 523 field: The descriptor of the map field to be converted. 524 525 Raises: 526 ParseError: In case of convert problems. 527 """ 528 if not isinstance(value, dict): 529 raise ParseError( 530 'Map field {0} must be in a dict which is {1}.'.format( 531 field.name, value)) 532 key_field = field.message_type.fields_by_name['key'] 533 value_field = field.message_type.fields_by_name['value'] 534 for key in value: 535 key_value = _ConvertScalarFieldValue(key, key_field, True) 536 if value_field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 537 self.ConvertMessage(value[key], getattr( 538 message, field.name)[key_value]) 539 else: 540 getattr(message, field.name)[key_value] = _ConvertScalarFieldValue( 541 value[key], value_field)
542 543
544 -def _ConvertScalarFieldValue(value, field, require_str=False):
545 """Convert a single scalar field value. 546 547 Args: 548 value: A scalar value to convert the scalar field value. 549 field: The descriptor of the field to convert. 550 require_str: If True, the field value must be a str. 551 552 Returns: 553 The converted scalar field value 554 555 Raises: 556 ParseError: In case of convert problems. 557 """ 558 if field.cpp_type in _INT_TYPES: 559 return _ConvertInteger(value) 560 elif field.cpp_type in _FLOAT_TYPES: 561 return _ConvertFloat(value) 562 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: 563 return _ConvertBool(value, require_str) 564 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: 565 if field.type == descriptor.FieldDescriptor.TYPE_BYTES: 566 return base64.b64decode(value) 567 else: 568 # Checking for unpaired surrogates appears to be unreliable, 569 # depending on the specific Python version, so we check manually. 570 if _UNPAIRED_SURROGATE_PATTERN.search(value): 571 raise ParseError('Unpaired surrogate') 572 return value 573 elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: 574 # Convert an enum value. 575 enum_value = field.enum_type.values_by_name.get(value, None) 576 if enum_value is None: 577 raise ParseError( 578 'Enum value must be a string literal with double quotes. ' 579 'Type "{0}" has no value named {1}.'.format( 580 field.enum_type.full_name, value)) 581 return enum_value.number
582 583
584 -def _ConvertInteger(value):
585 """Convert an integer. 586 587 Args: 588 value: A scalar value to convert. 589 590 Returns: 591 The integer value. 592 593 Raises: 594 ParseError: If an integer couldn't be consumed. 595 """ 596 if isinstance(value, float): 597 raise ParseError('Couldn\'t parse integer: {0}.'.format(value)) 598 599 if isinstance(value, six.text_type) and value.find(' ') != -1: 600 raise ParseError('Couldn\'t parse integer: "{0}".'.format(value)) 601 602 return int(value)
603 604
605 -def _ConvertFloat(value):
606 """Convert an floating point number.""" 607 if value == 'nan': 608 raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.') 609 try: 610 # Assume Python compatible syntax. 611 return float(value) 612 except ValueError: 613 # Check alternative spellings. 614 if value == _NEG_INFINITY: 615 return float('-inf') 616 elif value == _INFINITY: 617 return float('inf') 618 elif value == _NAN: 619 return float('nan') 620 else: 621 raise ParseError('Couldn\'t parse float: {0}.'.format(value))
622 623
624 -def _ConvertBool(value, require_str):
625 """Convert a boolean value. 626 627 Args: 628 value: A scalar value to convert. 629 require_str: If True, value must be a str. 630 631 Returns: 632 The bool parsed. 633 634 Raises: 635 ParseError: If a boolean value couldn't be consumed. 636 """ 637 if require_str: 638 if value == 'true': 639 return True 640 elif value == 'false': 641 return False 642 else: 643 raise ParseError('Expected "true" or "false", not {0}.'.format(value)) 644 645 if not isinstance(value, bool): 646 raise ParseError('Expected true or false without quotes.') 647 return value
648 649 _WKTJSONMETHODS = { 650 'google.protobuf.Any': ['_AnyMessageToJsonObject', 651 '_ConvertAnyMessage'], 652 'google.protobuf.Duration': ['_GenericMessageToJsonObject', 653 '_ConvertGenericMessage'], 654 'google.protobuf.FieldMask': ['_GenericMessageToJsonObject', 655 '_ConvertGenericMessage'], 656 'google.protobuf.ListValue': ['_ListValueMessageToJsonObject', 657 '_ConvertListValueMessage'], 658 'google.protobuf.Struct': ['_StructMessageToJsonObject', 659 '_ConvertStructMessage'], 660 'google.protobuf.Timestamp': ['_GenericMessageToJsonObject', 661 '_ConvertGenericMessage'], 662 'google.protobuf.Value': ['_ValueMessageToJsonObject', 663 '_ConvertValueMessage'] 664 }