31 package com.google.protobuf.util;
33 import com.
google.common.base.Preconditions;
35 import com.
google.errorprone.annotations.CanIgnoreReturnValue;
75 import java.io.IOException;
76 import java.io.Reader;
77 import java.io.StringReader;
78 import java.math.BigDecimal;
79 import java.math.BigInteger;
80 import java.text.ParseException;
81 import java.util.Collection;
82 import java.util.Collections;
83 import java.util.Comparator;
84 import java.util.HashMap;
85 import java.util.HashSet;
86 import java.util.List;
89 import java.util.TreeMap;
90 import java.util.logging.Logger;
112 false,
false,
false,
false);
160 throw new IllegalArgumentException(
"Only one registry is allowed.");
210 throw new IllegalStateException(
"JsonFormat printingEnumsAsInts has already been set.");
222 Preconditions.checkArgument(
223 null != fieldsToAlwaysOutput && !fieldsToAlwaysOutput.isEmpty(),
224 "Non-empty Set must be supplied for includingDefaultValueFields.");
230 Collections.unmodifiableSet(
new HashSet<>(fieldsToAlwaysOutput)),
239 throw new IllegalStateException(
240 "JsonFormat includingDefaultValueFields has already been set.");
341 StringBuilder builder =
new StringBuilder();
343 return builder.toString();
346 }
catch (IOException e) {
348 throw new IllegalStateException(e);
373 this.ignoringUnknownFields = ignoreUnknownFields;
385 throw new IllegalArgumentException(
"Only one registry is allowed.");
463 private final Map<String, Descriptor>
types;
478 @CanIgnoreReturnValue
481 throw new IllegalStateException(
"A TypeRegistry.Builer can only be used once.");
491 @CanIgnoreReturnValue
494 throw new IllegalStateException(
"A TypeRegistry.Builder can only be used once.");
532 logger.warning(
"Type " +
message.getFullName() +
" is added multiple times.");
539 private final Set<String>
files =
new HashSet<String>();
540 private Map<String, Descriptor>
types =
new HashMap<String, Descriptor>();
548 interface TextGenerator {
553 void print(
final CharSequence text)
throws IOException;
576 public void print(
final CharSequence text)
throws IOException {
585 private final StringBuilder
indent =
new StringBuilder();
607 throw new IllegalArgumentException(
" Outdent() without matching Indent().");
614 public void print(
final CharSequence text)
throws IOException {
615 final int size = text.length();
618 for (
int i = 0;
i <
size;
i++) {
619 if (text.charAt(
i) ==
'\n') {
620 write(text.subSequence(pos,
i + 1));
628 private void write(
final CharSequence
data)
throws IOException {
629 if (
data.length() == 0) {
665 Appendable jsonOutput,
666 boolean omittingInsignificantWhitespace,
677 if (omittingInsignificantWhitespace) {
679 this.blankOrSpace =
"";
680 this.blankOrNewLine =
"";
683 this.blankOrSpace =
" ";
684 this.blankOrNewLine =
"\n";
689 WellKnownTypePrinter specialPrinter =
691 if (specialPrinter !=
null) {
692 specialPrinter.print(
this,
message);
706 Map<String, WellKnownTypePrinter> printers =
new HashMap<String, WellKnownTypePrinter>();
709 Any.getDescriptor().getFullName(),
724 printers.put(
BoolValue.getDescriptor().getFullName(), wrappersPrinter);
725 printers.put(
Int32Value.getDescriptor().getFullName(), wrappersPrinter);
726 printers.put(
UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
727 printers.put(
Int64Value.getDescriptor().getFullName(), wrappersPrinter);
728 printers.put(
UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
729 printers.put(
StringValue.getDescriptor().getFullName(), wrappersPrinter);
730 printers.put(
BytesValue.getDescriptor().getFullName(), wrappersPrinter);
731 printers.put(
FloatValue.getDescriptor().getFullName(), wrappersPrinter);
732 printers.put(
DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
744 Duration.getDescriptor().getFullName(),
762 Struct.getDescriptor().getFullName(),
771 Value.getDescriptor().getFullName(),
792 if (
Any.getDefaultInstance().equals(
message)) {
801 if (typeUrlField ==
null
802 || valueField ==
null
807 String typeUrl = (String)
message.getField(typeUrlField);
829 print(contentMessage, typeUrl);
837 if (valueField ==
null) {
885 Map<FieldDescriptor, Object>
fields =
message.getAllFields();
916 boolean printedField =
false;
917 if (typeUrl !=
null) {
921 Map<FieldDescriptor, Object> fieldsToPrint =
null;
923 fieldsToPrint =
new TreeMap<FieldDescriptor, Object>(
message.getAllFields());
925 if (
field.isOptional()) {
938 if (!fieldsToPrint.containsKey(
field)
944 fieldsToPrint =
message.getAllFields();
970 if (
field.isMapField()) {
972 }
else if (
field.isRepeated()) {
979 @SuppressWarnings(
"rawtypes")
982 boolean printedElement =
false;
983 for (Object element : (List)
value) {
984 if (printedElement) {
987 printedElement =
true;
994 @SuppressWarnings(
"rawtypes")
999 if (keyField ==
null || valueField ==
null) {
1005 @SuppressWarnings(
"unchecked")
1006 Collection<Object> elements = (List<Object>)
value;
1008 Comparator<Object>
cmp =
null;
1010 cmp =
new Comparator<Object>() {
1012 public int compare(
final Object
o1,
final Object o2) {
1015 return ByteString.unsignedLexicographicalComparator().compare(s1, s2);
1019 TreeMap<Object, Object> tm =
new TreeMap<Object, Object>(
cmp);
1020 for (Object element : elements) {
1022 Object entryKey = entry.
getField(keyField);
1023 tm.put(entryKey, element);
1025 elements = tm.values();
1028 boolean printedElement =
false;
1029 for (Object element : elements) {
1031 Object entryKey = entry.
getField(keyField);
1032 Object entryValue = entry.
getField(valueField);
1033 if (printedElement) {
1036 printedElement =
true;
1043 if (printedElement) {
1062 throws IOException {
1063 switch (
field.getType()) {
1067 if (alwaysWithQuotes) {
1071 if (alwaysWithQuotes) {
1083 if (alwaysWithQuotes) {
1091 if (alwaysWithQuotes) {
1098 if (floatValue.isNaN()) {
1100 }
else if (floatValue.isInfinite()) {
1101 if (floatValue < 0) {
1107 if (alwaysWithQuotes) {
1111 if (alwaysWithQuotes) {
1119 if (doubleValue.isNaN()) {
1121 }
else if (doubleValue.isInfinite()) {
1122 if (doubleValue < 0) {
1128 if (alwaysWithQuotes) {
1131 generator.print(doubleValue.toString());
1132 if (alwaysWithQuotes) {
1140 if (alwaysWithQuotes) {
1144 if (alwaysWithQuotes) {
1166 if (
field.getEnumType().getFullName().equals(
"google.protobuf.NullValue")) {
1168 if (alwaysWithQuotes) {
1172 if (alwaysWithQuotes) {
1195 return Integer.toString(
value);
1197 return Long.toString(
value & 0x00000000FFFFFFFFL);
1204 return Long.toString(
value);
1208 return BigInteger.valueOf(
value & Long.MAX_VALUE).setBit(Long.SIZE - 1).toString();
1213 String[] parts = typeUrl.split(
"/");
1214 if (parts.length == 1) {
1217 return parts[parts.length - 1];
1229 this.ignoringUnknownFields = ignoreUnknownFields;
1230 this.jsonParser =
new JsonParser();
1232 this.currentDepth = 0;
1235 void merge(Reader json,
Message.
Builder builder)
throws IOException {
1237 JsonReader reader =
new JsonReader(json);
1238 reader.setLenient(
false);
1242 }
catch (JsonIOException e) {
1244 if (e.getCause() instanceof IOException) {
1245 throw (IOException) e.getCause();
1247 throw new InvalidProtocolBufferException(e.getMessage());
1249 }
catch (Exception e) {
1251 throw new InvalidProtocolBufferException(e.getMessage());
1255 void merge(String json, Message.Builder builder)
throws InvalidProtocolBufferException {
1257 JsonReader reader =
new JsonReader(
new StringReader(json));
1258 reader.setLenient(
false);
1260 }
catch (InvalidProtocolBufferException e) {
1262 }
catch (Exception e) {
1264 throw new InvalidProtocolBufferException(e.getMessage());
1277 Map<String, WellKnownTypeParser> parsers =
new HashMap<String, WellKnownTypeParser>();
1280 Any.getDescriptor().getFullName(),
1285 parser.mergeAny(json, builder);
1294 parser.mergeWrapper(json, builder);
1297 parsers.put(
BoolValue.getDescriptor().getFullName(), wrappersPrinter);
1298 parsers.put(
Int32Value.getDescriptor().getFullName(), wrappersPrinter);
1299 parsers.put(
UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
1300 parsers.put(
Int64Value.getDescriptor().getFullName(), wrappersPrinter);
1301 parsers.put(
UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
1302 parsers.put(
StringValue.getDescriptor().getFullName(), wrappersPrinter);
1303 parsers.put(
BytesValue.getDescriptor().getFullName(), wrappersPrinter);
1304 parsers.put(
FloatValue.getDescriptor().getFullName(), wrappersPrinter);
1305 parsers.put(
DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
1308 Timestamp.getDescriptor().getFullName(),
1313 parser.mergeTimestamp(json, builder);
1318 Duration.getDescriptor().getFullName(),
1323 parser.mergeDuration(json, builder);
1328 FieldMask.getDescriptor().getFullName(),
1333 parser.mergeFieldMask(json, builder);
1338 Struct.getDescriptor().getFullName(),
1343 parser.mergeStruct(json, builder);
1348 ListValue.getDescriptor().getFullName(),
1353 parser.mergeListValue(json, builder);
1358 Value.getDescriptor().getFullName(),
1363 parser.mergeValue(json, builder);
1373 if (specialParser !=
null) {
1374 specialParser.
merge(
this, json, builder);
1382 new HashMap<Descriptor, Map<String, FieldDescriptor>>();
1386 Map<String, FieldDescriptor> fieldNameMap =
new HashMap<String, FieldDescriptor>();
1389 fieldNameMap.put(
field.getJsonName(),
field);
1392 return fieldNameMap;
1399 if (!(json instanceof JsonObject)) {
1402 JsonObject
object = (JsonObject) json;
1403 Map<String, FieldDescriptor> fieldNameMap =
getFieldNameMap(builder.getDescriptorForType());
1404 for (
Map.Entry<String, JsonElement> entry :
object.entrySet()) {
1405 if (skipTypeUrl && entry.getKey().equals(
"@type")) {
1409 if (
field ==
null) {
1414 "Cannot find field: "
1417 + builder.getDescriptorForType().getFullName());
1430 if (typeUrlField ==
null
1431 || valueField ==
null
1437 if (!(json instanceof JsonObject)) {
1440 JsonObject
object = (JsonObject) json;
1441 if (
object.entrySet().isEmpty()) {
1444 JsonElement typeUrlElement =
object.get(
"@type");
1445 if (typeUrlElement ==
null) {
1448 String typeUrl = typeUrlElement.getAsString();
1450 if (contentType ==
null) {
1453 builder.setField(typeUrlField, typeUrl);
1457 if (specialParser !=
null) {
1458 JsonElement
value =
object.get(
"value");
1459 if (
value !=
null) {
1460 specialParser.
merge(
this,
value, contentBuilder);
1465 builder.setField(valueField, contentBuilder.build().toByteString());
1471 builder.mergeFrom(
value.toByteString());
1478 builder.mergeFrom(
value.toByteString());
1479 }
catch (ParseException e) {
1488 builder.mergeFrom(
value.toByteString());
1489 }
catch (ParseException e) {
1498 if (
field ==
null) {
1508 if (
field ==
null) {
1517 if (json instanceof JsonPrimitive) {
1518 JsonPrimitive primitive = (JsonPrimitive) json;
1519 if (primitive.isBoolean()) {
1520 builder.setField(
type.findFieldByName(
"bool_value"), primitive.getAsBoolean());
1521 }
else if (primitive.isNumber()) {
1522 builder.setField(
type.findFieldByName(
"number_value"), primitive.getAsDouble());
1524 builder.setField(
type.findFieldByName(
"string_value"), primitive.getAsString());
1526 }
else if (json instanceof JsonObject) {
1529 merge(json, structBuilder);
1530 builder.setField(
field, structBuilder.build());
1531 }
else if (json instanceof JsonArray) {
1534 merge(json, listBuilder);
1535 builder.setField(
field, listBuilder.build());
1536 }
else if (json instanceof JsonNull) {
1538 type.findFieldByName(
"null_value"),
NullValue.NULL_VALUE.getValueDescriptor());
1540 throw new IllegalStateException(
"Unexpected json data: " + json);
1548 if (
field ==
null) {
1556 if (
field.isRepeated()) {
1557 if (builder.getRepeatedFieldCount(
field) > 0) {
1559 "Field " +
field.getFullName() +
" has already been set.");
1562 if (builder.hasField(
field)) {
1564 "Field " +
field.getFullName() +
" has already been set.");
1567 if (
field.isRepeated() && json instanceof JsonNull) {
1572 if (
field.isMapField()) {
1574 }
else if (
field.isRepeated()) {
1576 }
else if (
field.getContainingOneof() !=
null) {
1580 if (
value !=
null) {
1589 if (!(json instanceof JsonObject)) {
1595 if (keyField ==
null || valueField ==
null) {
1598 JsonObject
object = (JsonObject) json;
1599 for (
Map.Entry<String, JsonElement> entry :
object.entrySet()) {
1601 Object
key =
parseFieldValue(keyField,
new JsonPrimitive(entry.getKey()), entryBuilder);
1603 if (
value ==
null) {
1610 entryBuilder.setField(keyField,
key);
1611 entryBuilder.setField(valueField,
value);
1612 builder.addRepeatedField(
field, entryBuilder.build());
1619 if (
value ==
null) {
1623 if (builder.getOneofFieldDescriptor(
field.getContainingOneof()) !=
null) {
1626 +
field.getFullName()
1627 +
" because another field "
1628 + builder.getOneofFieldDescriptor(
field.getContainingOneof()).getFullName()
1629 +
" belonging to the same oneof has already been set ");
1637 if (!(json instanceof JsonArray)) {
1640 JsonArray
array = (JsonArray) json;
1641 for (
int i = 0;
i <
array.size(); ++
i) {
1643 if (
value ==
null) {
1648 "Repeated field elements cannot be null in field: " +
field.getFullName());
1657 return Integer.parseInt(json.getAsString());
1658 }
catch (Exception e) {
1665 BigDecimal
value =
new BigDecimal(json.getAsString());
1666 return value.intValueExact();
1667 }
catch (Exception e) {
1674 return Long.parseLong(json.getAsString());
1675 }
catch (Exception e) {
1682 BigDecimal
value =
new BigDecimal(json.getAsString());
1683 return value.longValueExact();
1684 }
catch (Exception e) {
1691 long result = Long.parseLong(json.getAsString());
1692 if (result < 0 || result > 0xFFFFFFFFL) {
1695 return (
int) result;
1698 }
catch (Exception e) {
1705 BigDecimal decimalValue =
new BigDecimal(json.getAsString());
1706 BigInteger
value = decimalValue.toBigIntegerExact();
1707 if (
value.signum() < 0 ||
value.compareTo(
new BigInteger(
"FFFFFFFF", 16)) > 0) {
1710 return value.intValue();
1713 }
catch (Exception e) {
1718 private static final BigInteger
MAX_UINT64 =
new BigInteger(
"FFFFFFFFFFFFFFFF", 16);
1722 BigDecimal decimalValue =
new BigDecimal(json.getAsString());
1723 BigInteger
value = decimalValue.toBigIntegerExact();
1727 return value.longValue();
1730 }
catch (Exception e) {
1736 if (json.getAsString().equals(
"true")) {
1739 if (json.getAsString().equals(
"false")) {
1748 if (json.getAsString().equals(
"NaN")) {
1750 }
else if (json.getAsString().equals(
"Infinity")) {
1751 return Float.POSITIVE_INFINITY;
1752 }
else if (json.getAsString().equals(
"-Infinity")) {
1753 return Float.NEGATIVE_INFINITY;
1759 double value =
Double.parseDouble(json.getAsString());
1767 return (
float)
value;
1770 }
catch (Exception e) {
1785 if (json.getAsString().equals(
"NaN")) {
1787 }
else if (json.getAsString().equals(
"Infinity")) {
1788 return Double.POSITIVE_INFINITY;
1789 }
else if (json.getAsString().equals(
"-Infinity")) {
1790 return Double.NEGATIVE_INFINITY;
1796 BigDecimal
value =
new BigDecimal(json.getAsString());
1800 return value.doubleValue();
1803 }
catch (Exception e) {
1809 return json.getAsString();
1814 return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
1815 }
catch (IllegalArgumentException e) {
1816 return ByteString.copyFrom(BaseEncoding.base64Url().decode(json.getAsString()));
1822 String
value = json.getAsString();
1824 if (result ==
null) {
1829 result = enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue);
1831 result = enumDescriptor.findValueByNumber(numericValue);
1841 "Invalid enum value: " +
value +
" for enum type: " + enumDescriptor.getFullName());
1849 if (json instanceof JsonNull) {
1851 &&
field.getMessageType().getFullName().equals(
Value.getDescriptor().getFullName())) {
1855 return builder.newBuilderForField(
field).mergeFrom(
value.toByteString()).build();
1857 &&
field.getEnumType().getFullName().equals(
NullValue.getDescriptor().getFullName())) {
1859 return field.getEnumType().findValueByNumber(0);
1863 switch (
field.getType()) {
1907 merge(json, subBuilder);
1909 return subBuilder.build();