| Index: third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
|
| diff --git a/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c0eb03306ebd8f4eced6d3ce83d4d3e58b36352e
|
| --- /dev/null
|
| +++ b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
|
| @@ -0,0 +1,1156 @@
|
| +// Protocol Buffers - Google's data interchange format
|
| +// Copyright 2008 Google Inc. All rights reserved.
|
| +// https://developers.google.com/protocol-buffers/
|
| +//
|
| +// Redistribution and use in source and binary forms, with or without
|
| +// modification, are permitted provided that the following conditions are
|
| +// met:
|
| +//
|
| +// * Redistributions of source code must retain the above copyright
|
| +// notice, this list of conditions and the following disclaimer.
|
| +// * Redistributions in binary form must reproduce the above
|
| +// copyright notice, this list of conditions and the following disclaimer
|
| +// in the documentation and/or other materials provided with the
|
| +// distribution.
|
| +// * Neither the name of Google Inc. nor the names of its
|
| +// contributors may be used to endorse or promote products derived from
|
| +// this software without specific prior written permission.
|
| +//
|
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +package com.google.protobuf.util;
|
| +
|
| +import com.google.protobuf.Any;
|
| +import com.google.protobuf.BoolValue;
|
| +import com.google.protobuf.ByteString;
|
| +import com.google.protobuf.BytesValue;
|
| +import com.google.protobuf.DoubleValue;
|
| +import com.google.protobuf.FloatValue;
|
| +import com.google.protobuf.Int32Value;
|
| +import com.google.protobuf.Int64Value;
|
| +import com.google.protobuf.InvalidProtocolBufferException;
|
| +import com.google.protobuf.ListValue;
|
| +import com.google.protobuf.Message;
|
| +import com.google.protobuf.StringValue;
|
| +import com.google.protobuf.Struct;
|
| +import com.google.protobuf.UInt32Value;
|
| +import com.google.protobuf.UInt64Value;
|
| +import com.google.protobuf.Value;
|
| +import com.google.protobuf.util.JsonFormat.TypeRegistry;
|
| +import com.google.protobuf.util.JsonTestProto.TestAllTypes;
|
| +import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
|
| +import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
|
| +import com.google.protobuf.util.JsonTestProto.TestAny;
|
| +import com.google.protobuf.util.JsonTestProto.TestCustomJsonName;
|
| +import com.google.protobuf.util.JsonTestProto.TestDuration;
|
| +import com.google.protobuf.util.JsonTestProto.TestFieldMask;
|
| +import com.google.protobuf.util.JsonTestProto.TestMap;
|
| +import com.google.protobuf.util.JsonTestProto.TestOneof;
|
| +import com.google.protobuf.util.JsonTestProto.TestStruct;
|
| +import com.google.protobuf.util.JsonTestProto.TestTimestamp;
|
| +import com.google.protobuf.util.JsonTestProto.TestWrappers;
|
| +
|
| +import junit.framework.TestCase;
|
| +
|
| +import java.io.IOException;
|
| +import java.math.BigDecimal;
|
| +import java.math.BigInteger;
|
| +
|
| +public class JsonFormatTest extends TestCase {
|
| + private void setAllFields(TestAllTypes.Builder builder) {
|
| + builder.setOptionalInt32(1234);
|
| + builder.setOptionalInt64(1234567890123456789L);
|
| + builder.setOptionalUint32(5678);
|
| + builder.setOptionalUint64(2345678901234567890L);
|
| + builder.setOptionalSint32(9012);
|
| + builder.setOptionalSint64(3456789012345678901L);
|
| + builder.setOptionalFixed32(3456);
|
| + builder.setOptionalFixed64(4567890123456789012L);
|
| + builder.setOptionalSfixed32(7890);
|
| + builder.setOptionalSfixed64(5678901234567890123L);
|
| + builder.setOptionalFloat(1.5f);
|
| + builder.setOptionalDouble(1.25);
|
| + builder.setOptionalBool(true);
|
| + builder.setOptionalString("Hello world!");
|
| + builder.setOptionalBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
|
| + builder.setOptionalNestedEnum(NestedEnum.BAR);
|
| + builder.getOptionalNestedMessageBuilder().setValue(100);
|
| +
|
| + builder.addRepeatedInt32(1234);
|
| + builder.addRepeatedInt64(1234567890123456789L);
|
| + builder.addRepeatedUint32(5678);
|
| + builder.addRepeatedUint64(2345678901234567890L);
|
| + builder.addRepeatedSint32(9012);
|
| + builder.addRepeatedSint64(3456789012345678901L);
|
| + builder.addRepeatedFixed32(3456);
|
| + builder.addRepeatedFixed64(4567890123456789012L);
|
| + builder.addRepeatedSfixed32(7890);
|
| + builder.addRepeatedSfixed64(5678901234567890123L);
|
| + builder.addRepeatedFloat(1.5f);
|
| + builder.addRepeatedDouble(1.25);
|
| + builder.addRepeatedBool(true);
|
| + builder.addRepeatedString("Hello world!");
|
| + builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
|
| + builder.addRepeatedNestedEnum(NestedEnum.BAR);
|
| + builder.addRepeatedNestedMessageBuilder().setValue(100);
|
| +
|
| + builder.addRepeatedInt32(234);
|
| + builder.addRepeatedInt64(234567890123456789L);
|
| + builder.addRepeatedUint32(678);
|
| + builder.addRepeatedUint64(345678901234567890L);
|
| + builder.addRepeatedSint32(012);
|
| + builder.addRepeatedSint64(456789012345678901L);
|
| + builder.addRepeatedFixed32(456);
|
| + builder.addRepeatedFixed64(567890123456789012L);
|
| + builder.addRepeatedSfixed32(890);
|
| + builder.addRepeatedSfixed64(678901234567890123L);
|
| + builder.addRepeatedFloat(11.5f);
|
| + builder.addRepeatedDouble(11.25);
|
| + builder.addRepeatedBool(true);
|
| + builder.addRepeatedString("ello world!");
|
| + builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{1, 2}));
|
| + builder.addRepeatedNestedEnum(NestedEnum.BAZ);
|
| + builder.addRepeatedNestedMessageBuilder().setValue(200);
|
| + }
|
| +
|
| + private void assertRoundTripEquals(Message message) throws Exception {
|
| + assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
|
| + }
|
| +
|
| + private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
|
| + JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
|
| + JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
|
| + Message.Builder builder = message.newBuilderForType();
|
| + parser.merge(printer.print(message), builder);
|
| + Message parsedMessage = builder.build();
|
| + assertEquals(message.toString(), parsedMessage.toString());
|
| + }
|
| +
|
| + private String toJsonString(Message message) throws IOException {
|
| + return JsonFormat.printer().print(message);
|
| + }
|
| +
|
| + private void mergeFromJson(String json, Message.Builder builder) throws IOException {
|
| + JsonFormat.parser().merge(json, builder);
|
| + }
|
| +
|
| + public void testAllFields() throws Exception {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + setAllFields(builder);
|
| + TestAllTypes message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"optionalInt32\": 1234,\n"
|
| + + " \"optionalInt64\": \"1234567890123456789\",\n"
|
| + + " \"optionalUint32\": 5678,\n"
|
| + + " \"optionalUint64\": \"2345678901234567890\",\n"
|
| + + " \"optionalSint32\": 9012,\n"
|
| + + " \"optionalSint64\": \"3456789012345678901\",\n"
|
| + + " \"optionalFixed32\": 3456,\n"
|
| + + " \"optionalFixed64\": \"4567890123456789012\",\n"
|
| + + " \"optionalSfixed32\": 7890,\n"
|
| + + " \"optionalSfixed64\": \"5678901234567890123\",\n"
|
| + + " \"optionalFloat\": 1.5,\n"
|
| + + " \"optionalDouble\": 1.25,\n"
|
| + + " \"optionalBool\": true,\n"
|
| + + " \"optionalString\": \"Hello world!\",\n"
|
| + + " \"optionalBytes\": \"AAEC\",\n"
|
| + + " \"optionalNestedMessage\": {\n"
|
| + + " \"value\": 100\n"
|
| + + " },\n"
|
| + + " \"optionalNestedEnum\": \"BAR\",\n"
|
| + + " \"repeatedInt32\": [1234, 234],\n"
|
| + + " \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
|
| + + " \"repeatedUint32\": [5678, 678],\n"
|
| + + " \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
|
| + + " \"repeatedSint32\": [9012, 10],\n"
|
| + + " \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
|
| + + " \"repeatedFixed32\": [3456, 456],\n"
|
| + + " \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
|
| + + " \"repeatedSfixed32\": [7890, 890],\n"
|
| + + " \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
|
| + + " \"repeatedFloat\": [1.5, 11.5],\n"
|
| + + " \"repeatedDouble\": [1.25, 11.25],\n"
|
| + + " \"repeatedBool\": [true, true],\n"
|
| + + " \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
|
| + + " \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
|
| + + " \"repeatedNestedMessage\": [{\n"
|
| + + " \"value\": 100\n"
|
| + + " }, {\n"
|
| + + " \"value\": 200\n"
|
| + + " }],\n"
|
| + + " \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
|
| + + "}",
|
| + toJsonString(message));
|
| +
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testUnknownEnumValues() throws Exception {
|
| + TestAllTypes message = TestAllTypes.newBuilder()
|
| + .setOptionalNestedEnumValue(12345)
|
| + .addRepeatedNestedEnumValue(12345)
|
| + .addRepeatedNestedEnumValue(0)
|
| + .build();
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"optionalNestedEnum\": 12345,\n"
|
| + + " \"repeatedNestedEnum\": [12345, \"FOO\"]\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| +
|
| + TestMap.Builder mapBuilder = TestMap.newBuilder();
|
| + mapBuilder.getMutableInt32ToEnumMapValue().put(1, 0);
|
| + mapBuilder.getMutableInt32ToEnumMapValue().put(2, 12345);
|
| + TestMap mapMessage = mapBuilder.build();
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32ToEnumMap\": {\n"
|
| + + " \"1\": \"FOO\",\n"
|
| + + " \"2\": 12345\n"
|
| + + " }\n"
|
| + + "}", toJsonString(mapMessage));
|
| + assertRoundTripEquals(mapMessage);
|
| + }
|
| +
|
| + public void testSpecialFloatValues() throws Exception {
|
| + TestAllTypes message = TestAllTypes.newBuilder()
|
| + .addRepeatedFloat(Float.NaN)
|
| + .addRepeatedFloat(Float.POSITIVE_INFINITY)
|
| + .addRepeatedFloat(Float.NEGATIVE_INFINITY)
|
| + .addRepeatedDouble(Double.NaN)
|
| + .addRepeatedDouble(Double.POSITIVE_INFINITY)
|
| + .addRepeatedDouble(Double.NEGATIVE_INFINITY)
|
| + .build();
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
|
| + + " \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
|
| + + "}", toJsonString(message));
|
| +
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testParserAcceptStringForNumbericField() throws Exception {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalInt32\": \"1234\",\n"
|
| + + " \"optionalUint32\": \"5678\",\n"
|
| + + " \"optionalSint32\": \"9012\",\n"
|
| + + " \"optionalFixed32\": \"3456\",\n"
|
| + + " \"optionalSfixed32\": \"7890\",\n"
|
| + + " \"optionalFloat\": \"1.5\",\n"
|
| + + " \"optionalDouble\": \"1.25\",\n"
|
| + + " \"optionalBool\": \"true\"\n"
|
| + + "}", builder);
|
| + TestAllTypes message = builder.build();
|
| + assertEquals(1234, message.getOptionalInt32());
|
| + assertEquals(5678, message.getOptionalUint32());
|
| + assertEquals(9012, message.getOptionalSint32());
|
| + assertEquals(3456, message.getOptionalFixed32());
|
| + assertEquals(7890, message.getOptionalSfixed32());
|
| + assertEquals(1.5f, message.getOptionalFloat());
|
| + assertEquals(1.25, message.getOptionalDouble());
|
| + assertEquals(true, message.getOptionalBool());
|
| + }
|
| +
|
| + public void testParserAcceptFloatingPointValueForIntegerField() throws Exception {
|
| + // Test that numeric values like "1.000", "1e5" will also be accepted.
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"repeatedInt32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
|
| + + " \"repeatedUint32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
|
| + + " \"repeatedInt64\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
|
| + + " \"repeatedUint64\": [1.000, 1e5, \"1.000\", \"1e5\"]\n"
|
| + + "}", builder);
|
| + int[] expectedValues = new int[]{1, 100000, 1, 100000};
|
| + assertEquals(4, builder.getRepeatedInt32Count());
|
| + assertEquals(4, builder.getRepeatedUint32Count());
|
| + assertEquals(4, builder.getRepeatedInt64Count());
|
| + assertEquals(4, builder.getRepeatedUint64Count());
|
| + for (int i = 0; i < 4; ++i) {
|
| + assertEquals(expectedValues[i], builder.getRepeatedInt32(i));
|
| + assertEquals(expectedValues[i], builder.getRepeatedUint32(i));
|
| + assertEquals(expectedValues[i], builder.getRepeatedInt64(i));
|
| + assertEquals(expectedValues[i], builder.getRepeatedUint64(i));
|
| + }
|
| +
|
| + // Non-integers will still be rejected.
|
| + assertRejects("optionalInt32", "1.5");
|
| + assertRejects("optionalUint32", "1.5");
|
| + assertRejects("optionalInt64", "1.5");
|
| + assertRejects("optionalUint64", "1.5");
|
| + }
|
| +
|
| + private void assertRejects(String name, String value) {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + try {
|
| + // Numeric form is rejected.
|
| + mergeFromJson("{\"" + name + "\":" + value + "}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| + try {
|
| + // String form is also rejected.
|
| + mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| + }
|
| +
|
| + private void assertAccepts(String name, String value) throws IOException {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + // Both numeric form and string form are accepted.
|
| + mergeFromJson("{\"" + name + "\":" + value + "}", builder);
|
| + builder.clear();
|
| + mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
|
| + }
|
| +
|
| + public void testParserRejectOutOfRangeNumericValues() throws Exception {
|
| + assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
|
| + assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
|
| + assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
|
| + assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
|
| +
|
| + assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
|
| + assertRejects("optionalUint32", "123456789012345");
|
| + assertRejects("optionalUint32", "-1");
|
| +
|
| + BigInteger one = new BigInteger("1");
|
| + BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
|
| + BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
|
| + assertAccepts("optionalInt64", maxLong.toString());
|
| + assertAccepts("optionalInt64", minLong.toString());
|
| + assertRejects("optionalInt64", maxLong.add(one).toString());
|
| + assertRejects("optionalInt64", minLong.subtract(one).toString());
|
| +
|
| + assertAccepts("optionalUint64", maxLong.add(one).toString());
|
| + assertRejects("optionalUint64", "1234567890123456789012345");
|
| + assertRejects("optionalUint64", "-1");
|
| +
|
| + assertAccepts("optionalBool", "true");
|
| + assertRejects("optionalBool", "1");
|
| + assertRejects("optionalBool", "0");
|
| +
|
| + assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
|
| + assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
|
| + assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
|
| + assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
|
| +
|
| + BigDecimal moreThanOne = new BigDecimal("1.000001");
|
| + BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
|
| + BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
|
| + assertAccepts("optionalDouble", maxDouble.toString());
|
| + assertAccepts("optionalDouble", minDouble.toString());
|
| + assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
|
| + assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
|
| + }
|
| +
|
| + public void testParserAcceptNull() throws Exception {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalInt32\": null,\n"
|
| + + " \"optionalInt64\": null,\n"
|
| + + " \"optionalUint32\": null,\n"
|
| + + " \"optionalUint64\": null,\n"
|
| + + " \"optionalSint32\": null,\n"
|
| + + " \"optionalSint64\": null,\n"
|
| + + " \"optionalFixed32\": null,\n"
|
| + + " \"optionalFixed64\": null,\n"
|
| + + " \"optionalSfixed32\": null,\n"
|
| + + " \"optionalSfixed64\": null,\n"
|
| + + " \"optionalFloat\": null,\n"
|
| + + " \"optionalDouble\": null,\n"
|
| + + " \"optionalBool\": null,\n"
|
| + + " \"optionalString\": null,\n"
|
| + + " \"optionalBytes\": null,\n"
|
| + + " \"optionalNestedMessage\": null,\n"
|
| + + " \"optionalNestedEnum\": null,\n"
|
| + + " \"repeatedInt32\": null,\n"
|
| + + " \"repeatedInt64\": null,\n"
|
| + + " \"repeatedUint32\": null,\n"
|
| + + " \"repeatedUint64\": null,\n"
|
| + + " \"repeatedSint32\": null,\n"
|
| + + " \"repeatedSint64\": null,\n"
|
| + + " \"repeatedFixed32\": null,\n"
|
| + + " \"repeatedFixed64\": null,\n"
|
| + + " \"repeatedSfixed32\": null,\n"
|
| + + " \"repeatedSfixed64\": null,\n"
|
| + + " \"repeatedFloat\": null,\n"
|
| + + " \"repeatedDouble\": null,\n"
|
| + + " \"repeatedBool\": null,\n"
|
| + + " \"repeatedString\": null,\n"
|
| + + " \"repeatedBytes\": null,\n"
|
| + + " \"repeatedNestedMessage\": null,\n"
|
| + + " \"repeatedNestedEnum\": null\n"
|
| + + "}", builder);
|
| + TestAllTypes message = builder.build();
|
| + assertEquals(TestAllTypes.getDefaultInstance(), message);
|
| +
|
| + // Repeated field elements cannot be null.
|
| + try {
|
| + builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"repeatedInt32\": [null, null],\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| +
|
| + try {
|
| + builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"repeatedNestedMessage\": [null, null],\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| + }
|
| +
|
| + public void testParserRejectDuplicatedFields() throws Exception {
|
| + // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last
|
| + // one if multiple entries have the same name. This is not the desired behavior but it can
|
| + // only be fixed by using our own parser. Here we only test the cases where the names are
|
| + // different but still referring to the same field.
|
| +
|
| + // Duplicated optional fields.
|
| + try {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalNestedMessage\": {},\n"
|
| + + " \"optional_nested_message\": {}\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| +
|
| + // Duplicated repeated fields.
|
| + try {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"repeatedNestedMessage\": [null, null],\n"
|
| + + " \"repeated_nested_message\": [null, null]\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| +
|
| + // Duplicated oneof fields.
|
| + try {
|
| + TestOneof.Builder builder = TestOneof.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"oneofInt32\": 1,\n"
|
| + + " \"oneof_int32\": 2\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| + }
|
| +
|
| + public void testMapFields() throws Exception {
|
| + TestMap.Builder builder = TestMap.newBuilder();
|
| + builder.getMutableInt32ToInt32Map().put(1, 10);
|
| + builder.getMutableInt64ToInt32Map().put(1234567890123456789L, 10);
|
| + builder.getMutableUint32ToInt32Map().put(2, 20);
|
| + builder.getMutableUint64ToInt32Map().put(2234567890123456789L, 20);
|
| + builder.getMutableSint32ToInt32Map().put(3, 30);
|
| + builder.getMutableSint64ToInt32Map().put(3234567890123456789L, 30);
|
| + builder.getMutableFixed32ToInt32Map().put(4, 40);
|
| + builder.getMutableFixed64ToInt32Map().put(4234567890123456789L, 40);
|
| + builder.getMutableSfixed32ToInt32Map().put(5, 50);
|
| + builder.getMutableSfixed64ToInt32Map().put(5234567890123456789L, 50);
|
| + builder.getMutableBoolToInt32Map().put(false, 6);
|
| + builder.getMutableStringToInt32Map().put("Hello", 10);
|
| +
|
| + builder.getMutableInt32ToInt64Map().put(1, 1234567890123456789L);
|
| + builder.getMutableInt32ToUint32Map().put(2, 20);
|
| + builder.getMutableInt32ToUint64Map().put(2, 2234567890123456789L);
|
| + builder.getMutableInt32ToSint32Map().put(3, 30);
|
| + builder.getMutableInt32ToSint64Map().put(3, 3234567890123456789L);
|
| + builder.getMutableInt32ToFixed32Map().put(4, 40);
|
| + builder.getMutableInt32ToFixed64Map().put(4, 4234567890123456789L);
|
| + builder.getMutableInt32ToSfixed32Map().put(5, 50);
|
| + builder.getMutableInt32ToSfixed64Map().put(5, 5234567890123456789L);
|
| + builder.getMutableInt32ToFloatMap().put(6, 1.5f);
|
| + builder.getMutableInt32ToDoubleMap().put(6, 1.25);
|
| + builder.getMutableInt32ToBoolMap().put(7, false);
|
| + builder.getMutableInt32ToStringMap().put(7, "World");
|
| + builder.getMutableInt32ToBytesMap().put(
|
| + 8, ByteString.copyFrom(new byte[]{1, 2, 3}));
|
| + builder.getMutableInt32ToMessageMap().put(
|
| + 8, NestedMessage.newBuilder().setValue(1234).build());
|
| + builder.getMutableInt32ToEnumMap().put(9, NestedEnum.BAR);
|
| + TestMap message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32ToInt32Map\": {\n"
|
| + + " \"1\": 10\n"
|
| + + " },\n"
|
| + + " \"int64ToInt32Map\": {\n"
|
| + + " \"1234567890123456789\": 10\n"
|
| + + " },\n"
|
| + + " \"uint32ToInt32Map\": {\n"
|
| + + " \"2\": 20\n"
|
| + + " },\n"
|
| + + " \"uint64ToInt32Map\": {\n"
|
| + + " \"2234567890123456789\": 20\n"
|
| + + " },\n"
|
| + + " \"sint32ToInt32Map\": {\n"
|
| + + " \"3\": 30\n"
|
| + + " },\n"
|
| + + " \"sint64ToInt32Map\": {\n"
|
| + + " \"3234567890123456789\": 30\n"
|
| + + " },\n"
|
| + + " \"fixed32ToInt32Map\": {\n"
|
| + + " \"4\": 40\n"
|
| + + " },\n"
|
| + + " \"fixed64ToInt32Map\": {\n"
|
| + + " \"4234567890123456789\": 40\n"
|
| + + " },\n"
|
| + + " \"sfixed32ToInt32Map\": {\n"
|
| + + " \"5\": 50\n"
|
| + + " },\n"
|
| + + " \"sfixed64ToInt32Map\": {\n"
|
| + + " \"5234567890123456789\": 50\n"
|
| + + " },\n"
|
| + + " \"boolToInt32Map\": {\n"
|
| + + " \"false\": 6\n"
|
| + + " },\n"
|
| + + " \"stringToInt32Map\": {\n"
|
| + + " \"Hello\": 10\n"
|
| + + " },\n"
|
| + + " \"int32ToInt64Map\": {\n"
|
| + + " \"1\": \"1234567890123456789\"\n"
|
| + + " },\n"
|
| + + " \"int32ToUint32Map\": {\n"
|
| + + " \"2\": 20\n"
|
| + + " },\n"
|
| + + " \"int32ToUint64Map\": {\n"
|
| + + " \"2\": \"2234567890123456789\"\n"
|
| + + " },\n"
|
| + + " \"int32ToSint32Map\": {\n"
|
| + + " \"3\": 30\n"
|
| + + " },\n"
|
| + + " \"int32ToSint64Map\": {\n"
|
| + + " \"3\": \"3234567890123456789\"\n"
|
| + + " },\n"
|
| + + " \"int32ToFixed32Map\": {\n"
|
| + + " \"4\": 40\n"
|
| + + " },\n"
|
| + + " \"int32ToFixed64Map\": {\n"
|
| + + " \"4\": \"4234567890123456789\"\n"
|
| + + " },\n"
|
| + + " \"int32ToSfixed32Map\": {\n"
|
| + + " \"5\": 50\n"
|
| + + " },\n"
|
| + + " \"int32ToSfixed64Map\": {\n"
|
| + + " \"5\": \"5234567890123456789\"\n"
|
| + + " },\n"
|
| + + " \"int32ToFloatMap\": {\n"
|
| + + " \"6\": 1.5\n"
|
| + + " },\n"
|
| + + " \"int32ToDoubleMap\": {\n"
|
| + + " \"6\": 1.25\n"
|
| + + " },\n"
|
| + + " \"int32ToBoolMap\": {\n"
|
| + + " \"7\": false\n"
|
| + + " },\n"
|
| + + " \"int32ToStringMap\": {\n"
|
| + + " \"7\": \"World\"\n"
|
| + + " },\n"
|
| + + " \"int32ToBytesMap\": {\n"
|
| + + " \"8\": \"AQID\"\n"
|
| + + " },\n"
|
| + + " \"int32ToMessageMap\": {\n"
|
| + + " \"8\": {\n"
|
| + + " \"value\": 1234\n"
|
| + + " }\n"
|
| + + " },\n"
|
| + + " \"int32ToEnumMap\": {\n"
|
| + + " \"9\": \"BAR\"\n"
|
| + + " }\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| +
|
| + // Test multiple entries.
|
| + builder = TestMap.newBuilder();
|
| + builder.getMutableInt32ToInt32Map().put(1, 2);
|
| + builder.getMutableInt32ToInt32Map().put(3, 4);
|
| + message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32ToInt32Map\": {\n"
|
| + + " \"1\": 2,\n"
|
| + + " \"3\": 4\n"
|
| + + " }\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testMapNullValueIsRejected() throws Exception {
|
| + try {
|
| + TestMap.Builder builder = TestMap.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"int32ToInt32Map\": {null: 1},\n"
|
| + + " \"int32ToMessageMap\": {null: 2}\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| +
|
| + try {
|
| + TestMap.Builder builder = TestMap.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"int32ToInt32Map\": {\"1\": null},\n"
|
| + + " \"int32ToMessageMap\": {\"2\": null}\n"
|
| + + "}", builder);
|
| + fail();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Exception expected.
|
| + }
|
| + }
|
| +
|
| + public void testParserAcceptNonQuotedObjectKey() throws Exception {
|
| + TestMap.Builder builder = TestMap.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " int32ToInt32Map: {1: 2},\n"
|
| + + " stringToInt32Map: {hello: 3}\n"
|
| + + "}", builder);
|
| + TestMap message = builder.build();
|
| + assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
|
| + assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
|
| + }
|
| +
|
| + public void testWrappers() throws Exception {
|
| + TestWrappers.Builder builder = TestWrappers.newBuilder();
|
| + builder.getBoolValueBuilder().setValue(false);
|
| + builder.getInt32ValueBuilder().setValue(0);
|
| + builder.getInt64ValueBuilder().setValue(0);
|
| + builder.getUint32ValueBuilder().setValue(0);
|
| + builder.getUint64ValueBuilder().setValue(0);
|
| + builder.getFloatValueBuilder().setValue(0.0f);
|
| + builder.getDoubleValueBuilder().setValue(0.0);
|
| + builder.getStringValueBuilder().setValue("");
|
| + builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
|
| + TestWrappers message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32Value\": 0,\n"
|
| + + " \"uint32Value\": 0,\n"
|
| + + " \"int64Value\": \"0\",\n"
|
| + + " \"uint64Value\": \"0\",\n"
|
| + + " \"floatValue\": 0.0,\n"
|
| + + " \"doubleValue\": 0.0,\n"
|
| + + " \"boolValue\": false,\n"
|
| + + " \"stringValue\": \"\",\n"
|
| + + " \"bytesValue\": \"\"\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| +
|
| + builder = TestWrappers.newBuilder();
|
| + builder.getBoolValueBuilder().setValue(true);
|
| + builder.getInt32ValueBuilder().setValue(1);
|
| + builder.getInt64ValueBuilder().setValue(2);
|
| + builder.getUint32ValueBuilder().setValue(3);
|
| + builder.getUint64ValueBuilder().setValue(4);
|
| + builder.getFloatValueBuilder().setValue(5.0f);
|
| + builder.getDoubleValueBuilder().setValue(6.0);
|
| + builder.getStringValueBuilder().setValue("7");
|
| + builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[]{8}));
|
| + message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32Value\": 1,\n"
|
| + + " \"uint32Value\": 3,\n"
|
| + + " \"int64Value\": \"2\",\n"
|
| + + " \"uint64Value\": \"4\",\n"
|
| + + " \"floatValue\": 5.0,\n"
|
| + + " \"doubleValue\": 6.0,\n"
|
| + + " \"boolValue\": true,\n"
|
| + + " \"stringValue\": \"7\",\n"
|
| + + " \"bytesValue\": \"CA==\"\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testTimestamp() throws Exception {
|
| + TestTimestamp message = TestTimestamp.newBuilder()
|
| + .setTimestampValue(TimeUtil.parseTimestamp("1970-01-01T00:00:00Z"))
|
| + .build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"timestampValue\": \"1970-01-01T00:00:00Z\"\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testDuration() throws Exception {
|
| + TestDuration message = TestDuration.newBuilder()
|
| + .setDurationValue(TimeUtil.parseDuration("12345s"))
|
| + .build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"durationValue\": \"12345s\"\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testFieldMask() throws Exception {
|
| + TestFieldMask message = TestFieldMask.newBuilder()
|
| + .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz"))
|
| + .build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"fieldMaskValue\": \"foo.bar,baz\"\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testStruct() throws Exception {
|
| + // Build a struct with all possible values.
|
| + TestStruct.Builder builder = TestStruct.newBuilder();
|
| + Struct.Builder structBuilder = builder.getStructValueBuilder();
|
| + structBuilder.getMutableFields().put(
|
| + "null_value", Value.newBuilder().setNullValueValue(0).build());
|
| + structBuilder.getMutableFields().put(
|
| + "number_value", Value.newBuilder().setNumberValue(1.25).build());
|
| + structBuilder.getMutableFields().put(
|
| + "string_value", Value.newBuilder().setStringValue("hello").build());
|
| + Struct.Builder subStructBuilder = Struct.newBuilder();
|
| + subStructBuilder.getMutableFields().put(
|
| + "number_value", Value.newBuilder().setNumberValue(1234).build());
|
| + structBuilder.getMutableFields().put(
|
| + "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
|
| + ListValue.Builder listBuilder = ListValue.newBuilder();
|
| + listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
|
| + listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
|
| + structBuilder.getMutableFields().put(
|
| + "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
|
| + TestStruct message = builder.build();
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"structValue\": {\n"
|
| + + " \"null_value\": null,\n"
|
| + + " \"number_value\": 1.25,\n"
|
| + + " \"string_value\": \"hello\",\n"
|
| + + " \"struct_value\": {\n"
|
| + + " \"number_value\": 1234.0\n"
|
| + + " },\n"
|
| + + " \"list_value\": [1.125, null]\n"
|
| + + " }\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| +
|
| + builder = TestStruct.newBuilder();
|
| + builder.setValue(Value.newBuilder().setNullValueValue(0).build());
|
| + message = builder.build();
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"value\": null\n"
|
| + + "}", toJsonString(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testAnyFields() throws Exception {
|
| + TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
|
| + TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
|
| +
|
| + // A TypeRegistry must be provided in order to convert Any types.
|
| + try {
|
| + toJsonString(message);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| +
|
| + JsonFormat.TypeRegistry registry = JsonFormat.TypeRegistry.newBuilder()
|
| + .add(TestAllTypes.getDescriptor()).build();
|
| + JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
|
| +
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"anyValue\": {\n"
|
| + + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
|
| + + " \"optionalInt32\": 1234\n"
|
| + + " }\n"
|
| + + "}" , printer.print(message));
|
| + assertRoundTripEquals(message, registry);
|
| +
|
| +
|
| + // Well-known types have a special formatting when embedded in Any.
|
| + //
|
| + // 1. Any in Any.
|
| + Any anyMessage = Any.pack(Any.pack(content));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
|
| + + " \"value\": {\n"
|
| + + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
|
| + + " \"optionalInt32\": 1234\n"
|
| + + " }\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| +
|
| + // 2. Wrappers in Any.
|
| + anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
|
| + + " \"value\": 12345\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
|
| + + " \"value\": 12345\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
|
| + + " \"value\": \"12345\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
|
| + + " \"value\": \"12345\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
|
| + + " \"value\": 12345.0\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
|
| + + " \"value\": 12345.0\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
|
| + + " \"value\": true\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
|
| + + " \"value\": \"Hello\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + anyMessage = Any.pack(BytesValue.newBuilder().setValue(
|
| + ByteString.copyFrom(new byte[]{1, 2})).build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
|
| + + " \"value\": \"AQI=\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| +
|
| + // 3. Timestamp in Any.
|
| + anyMessage = Any.pack(TimeUtil.parseTimestamp("1969-12-31T23:59:59Z"));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
|
| + + " \"value\": \"1969-12-31T23:59:59Z\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| +
|
| + // 4. Duration in Any
|
| + anyMessage = Any.pack(TimeUtil.parseDuration("12345.10s"));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
|
| + + " \"value\": \"12345.100s\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| +
|
| + // 5. FieldMask in Any
|
| + anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
|
| + + " \"value\": \"foo.bar,baz\"\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| +
|
| + // 6. Struct in Any
|
| + Struct.Builder structBuilder = Struct.newBuilder();
|
| + structBuilder.getMutableFields().put(
|
| + "number", Value.newBuilder().setNumberValue(1.125).build());
|
| + anyMessage = Any.pack(structBuilder.build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
|
| + + " \"value\": {\n"
|
| + + " \"number\": 1.125\n"
|
| + + " }\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + Value.Builder valueBuilder = Value.newBuilder();
|
| + valueBuilder.setNumberValue(1);
|
| + anyMessage = Any.pack(valueBuilder.build());
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
|
| + + " \"value\": 1.0\n"
|
| + + "}", printer.print(anyMessage));
|
| + assertRoundTripEquals(anyMessage, registry);
|
| + }
|
| +
|
| + public void testParserMissingTypeUrl() throws Exception {
|
| + try {
|
| + Any.Builder builder = Any.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalInt32\": 1234\n"
|
| + + "}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| + }
|
| +
|
| + public void testParserUnexpectedTypeUrl() throws Exception {
|
| + try {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
|
| + + " \"optionalInt32\": 12345\n"
|
| + + "}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| + }
|
| +
|
| + public void testParserRejectTrailingComma() throws Exception {
|
| + try {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalInt32\": 12345,\n"
|
| + + "}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (IOException e) {
|
| + // Expected.
|
| + }
|
| +
|
| + // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
|
| + // the JsonReader to non-lenient mode. If we want to enforce strict JSON
|
| + // compliance, we might want to switch to a different JSON parser or
|
| + // implement one by ourselves.
|
| + // try {
|
| + // TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + // JsonFormat.merge(
|
| + // "{\n"
|
| + // + " \"repeatedInt32\": [12345,]\n"
|
| + // + "}", builder);
|
| + // fail("Exception is expected.");
|
| + // } catch (IOException e) {
|
| + // // Expected.
|
| + // }
|
| + }
|
| +
|
| + public void testParserRejectInvalidBase64() throws Exception {
|
| + assertRejects("optionalBytes", "!@#$");
|
| + // We use standard BASE64 with paddings.
|
| + assertRejects("optionalBytes", "AQI");
|
| + }
|
| +
|
| + public void testParserRejectInvalidEnumValue() throws Exception {
|
| + try {
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + mergeFromJson(
|
| + "{\n"
|
| + + " \"optionalNestedEnum\": \"XXX\"\n"
|
| + + "}", builder);
|
| + fail("Exception is expected.");
|
| + } catch (InvalidProtocolBufferException e) {
|
| + // Expected.
|
| + }
|
| + }
|
| +
|
| + public void testCustomJsonName() throws Exception {
|
| + TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
|
| + assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
|
| + assertRoundTripEquals(message);
|
| + }
|
| +
|
| + public void testIncludingDefaultValueFields() throws Exception {
|
| + TestAllTypes message = TestAllTypes.getDefaultInstance();
|
| + assertEquals("{\n}", JsonFormat.printer().print(message));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"optionalInt32\": 0,\n"
|
| + + " \"optionalInt64\": \"0\",\n"
|
| + + " \"optionalUint32\": 0,\n"
|
| + + " \"optionalUint64\": \"0\",\n"
|
| + + " \"optionalSint32\": 0,\n"
|
| + + " \"optionalSint64\": \"0\",\n"
|
| + + " \"optionalFixed32\": 0,\n"
|
| + + " \"optionalFixed64\": \"0\",\n"
|
| + + " \"optionalSfixed32\": 0,\n"
|
| + + " \"optionalSfixed64\": \"0\",\n"
|
| + + " \"optionalFloat\": 0.0,\n"
|
| + + " \"optionalDouble\": 0.0,\n"
|
| + + " \"optionalBool\": false,\n"
|
| + + " \"optionalString\": \"\",\n"
|
| + + " \"optionalBytes\": \"\",\n"
|
| + + " \"optionalNestedEnum\": \"FOO\",\n"
|
| + + " \"repeatedInt32\": [],\n"
|
| + + " \"repeatedInt64\": [],\n"
|
| + + " \"repeatedUint32\": [],\n"
|
| + + " \"repeatedUint64\": [],\n"
|
| + + " \"repeatedSint32\": [],\n"
|
| + + " \"repeatedSint64\": [],\n"
|
| + + " \"repeatedFixed32\": [],\n"
|
| + + " \"repeatedFixed64\": [],\n"
|
| + + " \"repeatedSfixed32\": [],\n"
|
| + + " \"repeatedSfixed64\": [],\n"
|
| + + " \"repeatedFloat\": [],\n"
|
| + + " \"repeatedDouble\": [],\n"
|
| + + " \"repeatedBool\": [],\n"
|
| + + " \"repeatedString\": [],\n"
|
| + + " \"repeatedBytes\": [],\n"
|
| + + " \"repeatedNestedMessage\": [],\n"
|
| + + " \"repeatedNestedEnum\": []\n"
|
| + + "}",
|
| + JsonFormat.printer().includingDefaultValueFields().print(message));
|
| +
|
| + TestMap mapMessage = TestMap.getDefaultInstance();
|
| + assertEquals("{\n}", JsonFormat.printer().print(mapMessage));
|
| + assertEquals(
|
| + "{\n"
|
| + + " \"int32ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int64ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"uint32ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"uint64ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"sint32ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"sint64ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"fixed32ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"fixed64ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"sfixed32ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"sfixed64ToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"boolToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"stringToInt32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToInt64Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToUint32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToUint64Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToSint32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToSint64Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToFixed32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToFixed64Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToSfixed32Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToSfixed64Map\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToFloatMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToDoubleMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToBoolMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToStringMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToBytesMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToMessageMap\": {\n"
|
| + + " },\n"
|
| + + " \"int32ToEnumMap\": {\n"
|
| + + " }\n"
|
| + + "}",
|
| + JsonFormat.printer().includingDefaultValueFields().print(mapMessage));
|
| + }
|
| +
|
| + public void testPreservingProtoFieldNames() throws Exception {
|
| + TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
|
| + assertEquals("{\n" + " \"optionalInt32\": 12345\n" + "}", JsonFormat.printer().print(message));
|
| + assertEquals(
|
| + "{\n" + " \"optional_int32\": 12345\n" + "}",
|
| + JsonFormat.printer().preservingProtoFieldNames().print(message));
|
| +
|
| + // The json_name field option is ignored when configured to use original proto field names.
|
| + TestCustomJsonName messageWithCustomJsonName =
|
| + TestCustomJsonName.newBuilder().setValue(12345).build();
|
| + assertEquals(
|
| + "{\n" + " \"value\": 12345\n" + "}",
|
| + JsonFormat.printer().preservingProtoFieldNames().print(messageWithCustomJsonName));
|
| +
|
| + // Parsers accept both original proto field names and lowerCamelCase names.
|
| + TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
| + JsonFormat.parser().merge("{\"optionalInt32\": 12345}", builder);
|
| + assertEquals(12345, builder.getOptionalInt32());
|
| + builder.clear();
|
| + JsonFormat.parser().merge("{\"optional_int32\": 54321}", builder);
|
| + assertEquals(54321, builder.getOptionalInt32());
|
| + }
|
| +}
|
|
|