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 package com.google.protobuf.util;
32 
33 import com.google.protobuf.Any;
34 import com.google.protobuf.BoolValue;
35 import com.google.protobuf.ByteString;
36 import com.google.protobuf.BytesValue;
37 import com.google.protobuf.Descriptors.Descriptor;
38 import com.google.protobuf.Descriptors.FieldDescriptor;
39 import com.google.protobuf.DoubleValue;
40 import com.google.protobuf.FloatValue;
41 import com.google.protobuf.Int32Value;
42 import com.google.protobuf.Int64Value;
43 import com.google.protobuf.InvalidProtocolBufferException;
44 import com.google.protobuf.ListValue;
45 import com.google.protobuf.Message;
46 import com.google.protobuf.NullValue;
47 import com.google.protobuf.StringValue;
48 import com.google.protobuf.Struct;
49 import com.google.protobuf.UInt32Value;
50 import com.google.protobuf.UInt64Value;
51 import com.google.protobuf.Value;
52 import com.google.protobuf.util.JsonFormat.TypeRegistry;
53 import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes;
54 import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.AliasedEnum;
55 import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedEnum;
56 import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedMessage;
57 import com.google.protobuf.util.proto.JsonTestProto.TestAny;
58 import com.google.protobuf.util.proto.JsonTestProto.TestCustomJsonName;
59 import com.google.protobuf.util.proto.JsonTestProto.TestDuration;
60 import com.google.protobuf.util.proto.JsonTestProto.TestFieldMask;
61 import com.google.protobuf.util.proto.JsonTestProto.TestMap;
62 import com.google.protobuf.util.proto.JsonTestProto.TestOneof;
63 import com.google.protobuf.util.proto.JsonTestProto.TestRecursive;
64 import com.google.protobuf.util.proto.JsonTestProto.TestStruct;
65 import com.google.protobuf.util.proto.JsonTestProto.TestTimestamp;
66 import com.google.protobuf.util.proto.JsonTestProto.TestWrappers;
67 import java.io.IOException;
68 import java.io.InputStream;
69 import java.io.InputStreamReader;
70 import java.io.Reader;
71 import java.io.StringReader;
72 import java.math.BigDecimal;
73 import java.math.BigInteger;
74 import java.util.Collections;
75 import java.util.HashSet;
76 import java.util.Locale;
77 import java.util.Set;
78 import junit.framework.TestCase;
79 
80 public class JsonFormatTest extends TestCase {
JsonFormatTest()81   public JsonFormatTest() {
82     // Test that locale does not affect JsonFormat.
83     Locale.setDefault(Locale.forLanguageTag("hi-IN"));
84   }
85 
setAllFields(TestAllTypes.Builder builder)86   private void setAllFields(TestAllTypes.Builder builder) {
87     builder.setOptionalInt32(1234);
88     builder.setOptionalInt64(1234567890123456789L);
89     builder.setOptionalUint32(5678);
90     builder.setOptionalUint64(2345678901234567890L);
91     builder.setOptionalSint32(9012);
92     builder.setOptionalSint64(3456789012345678901L);
93     builder.setOptionalFixed32(3456);
94     builder.setOptionalFixed64(4567890123456789012L);
95     builder.setOptionalSfixed32(7890);
96     builder.setOptionalSfixed64(5678901234567890123L);
97     builder.setOptionalFloat(1.5f);
98     builder.setOptionalDouble(1.25);
99     builder.setOptionalBool(true);
100     builder.setOptionalString("Hello world!");
101     builder.setOptionalBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
102     builder.setOptionalNestedEnum(NestedEnum.BAR);
103     builder.getOptionalNestedMessageBuilder().setValue(100);
104 
105     builder.addRepeatedInt32(1234);
106     builder.addRepeatedInt64(1234567890123456789L);
107     builder.addRepeatedUint32(5678);
108     builder.addRepeatedUint64(2345678901234567890L);
109     builder.addRepeatedSint32(9012);
110     builder.addRepeatedSint64(3456789012345678901L);
111     builder.addRepeatedFixed32(3456);
112     builder.addRepeatedFixed64(4567890123456789012L);
113     builder.addRepeatedSfixed32(7890);
114     builder.addRepeatedSfixed64(5678901234567890123L);
115     builder.addRepeatedFloat(1.5f);
116     builder.addRepeatedDouble(1.25);
117     builder.addRepeatedBool(true);
118     builder.addRepeatedString("Hello world!");
119     builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
120     builder.addRepeatedNestedEnum(NestedEnum.BAR);
121     builder.addRepeatedNestedMessageBuilder().setValue(100);
122 
123     builder.addRepeatedInt32(234);
124     builder.addRepeatedInt64(234567890123456789L);
125     builder.addRepeatedUint32(678);
126     builder.addRepeatedUint64(345678901234567890L);
127     builder.addRepeatedSint32(012);
128     builder.addRepeatedSint64(456789012345678901L);
129     builder.addRepeatedFixed32(456);
130     builder.addRepeatedFixed64(567890123456789012L);
131     builder.addRepeatedSfixed32(890);
132     builder.addRepeatedSfixed64(678901234567890123L);
133     builder.addRepeatedFloat(11.5f);
134     builder.addRepeatedDouble(11.25);
135     builder.addRepeatedBool(true);
136     builder.addRepeatedString("ello world!");
137     builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {1, 2}));
138     builder.addRepeatedNestedEnum(NestedEnum.BAZ);
139     builder.addRepeatedNestedMessageBuilder().setValue(200);
140   }
141 
assertRoundTripEquals(Message message)142   private void assertRoundTripEquals(Message message) throws Exception {
143     assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
144   }
145 
assertRoundTripEquals(Message message, TypeRegistry registry)146   private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
147     JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
148     JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
149     Message.Builder builder = message.newBuilderForType();
150     parser.merge(printer.print(message), builder);
151     Message parsedMessage = builder.build();
152     assertEquals(message.toString(), parsedMessage.toString());
153   }
154 
toJsonString(Message message)155   private String toJsonString(Message message) throws IOException {
156     return JsonFormat.printer().print(message);
157   }
toCompactJsonString(Message message)158   private String toCompactJsonString(Message message) throws IOException {
159     return JsonFormat.printer().omittingInsignificantWhitespace().print(message);
160   }
toSortedJsonString(Message message)161   private String toSortedJsonString(Message message) throws IOException {
162     return JsonFormat.printer().sortingMapKeys().print(message);
163   }
164 
mergeFromJson(String json, Message.Builder builder)165   private void mergeFromJson(String json, Message.Builder builder) throws IOException {
166     JsonFormat.parser().merge(json, builder);
167   }
168 
mergeFromJsonIgnoringUnknownFields(String json, Message.Builder builder)169   private void mergeFromJsonIgnoringUnknownFields(String json, Message.Builder builder)
170       throws IOException {
171     JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
172   }
173 
testAllFields()174   public void testAllFields() throws Exception {
175     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
176     setAllFields(builder);
177     TestAllTypes message = builder.build();
178 
179     assertEquals(
180         "{\n"
181             + "  \"optionalInt32\": 1234,\n"
182             + "  \"optionalInt64\": \"1234567890123456789\",\n"
183             + "  \"optionalUint32\": 5678,\n"
184             + "  \"optionalUint64\": \"2345678901234567890\",\n"
185             + "  \"optionalSint32\": 9012,\n"
186             + "  \"optionalSint64\": \"3456789012345678901\",\n"
187             + "  \"optionalFixed32\": 3456,\n"
188             + "  \"optionalFixed64\": \"4567890123456789012\",\n"
189             + "  \"optionalSfixed32\": 7890,\n"
190             + "  \"optionalSfixed64\": \"5678901234567890123\",\n"
191             + "  \"optionalFloat\": 1.5,\n"
192             + "  \"optionalDouble\": 1.25,\n"
193             + "  \"optionalBool\": true,\n"
194             + "  \"optionalString\": \"Hello world!\",\n"
195             + "  \"optionalBytes\": \"AAEC\",\n"
196             + "  \"optionalNestedMessage\": {\n"
197             + "    \"value\": 100\n"
198             + "  },\n"
199             + "  \"optionalNestedEnum\": \"BAR\",\n"
200             + "  \"repeatedInt32\": [1234, 234],\n"
201             + "  \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
202             + "  \"repeatedUint32\": [5678, 678],\n"
203             + "  \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
204             + "  \"repeatedSint32\": [9012, 10],\n"
205             + "  \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
206             + "  \"repeatedFixed32\": [3456, 456],\n"
207             + "  \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
208             + "  \"repeatedSfixed32\": [7890, 890],\n"
209             + "  \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
210             + "  \"repeatedFloat\": [1.5, 11.5],\n"
211             + "  \"repeatedDouble\": [1.25, 11.25],\n"
212             + "  \"repeatedBool\": [true, true],\n"
213             + "  \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
214             + "  \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
215             + "  \"repeatedNestedMessage\": [{\n"
216             + "    \"value\": 100\n"
217             + "  }, {\n"
218             + "    \"value\": 200\n"
219             + "  }],\n"
220             + "  \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
221             + "}",
222         toJsonString(message));
223 
224     assertRoundTripEquals(message);
225   }
226 
testUnknownEnumValues()227   public void testUnknownEnumValues() throws Exception {
228     TestAllTypes message =
229         TestAllTypes.newBuilder()
230             .setOptionalNestedEnumValue(12345)
231             .addRepeatedNestedEnumValue(12345)
232             .addRepeatedNestedEnumValue(0)
233             .build();
234     assertEquals(
235         "{\n"
236             + "  \"optionalNestedEnum\": 12345,\n"
237             + "  \"repeatedNestedEnum\": [12345, \"FOO\"]\n"
238             + "}",
239         toJsonString(message));
240     assertRoundTripEquals(message);
241 
242     TestMap.Builder mapBuilder = TestMap.newBuilder();
243     mapBuilder.putInt32ToEnumMapValue(1, 0);
244     mapBuilder.putInt32ToEnumMapValue(2, 12345);
245     TestMap mapMessage = mapBuilder.build();
246     assertEquals(
247         "{\n"
248             + "  \"int32ToEnumMap\": {\n"
249             + "    \"1\": \"FOO\",\n"
250             + "    \"2\": 12345\n"
251             + "  }\n"
252             + "}",
253         toJsonString(mapMessage));
254     assertRoundTripEquals(mapMessage);
255   }
256 
testSpecialFloatValues()257   public void testSpecialFloatValues() throws Exception {
258     TestAllTypes message =
259         TestAllTypes.newBuilder()
260             .addRepeatedFloat(Float.NaN)
261             .addRepeatedFloat(Float.POSITIVE_INFINITY)
262             .addRepeatedFloat(Float.NEGATIVE_INFINITY)
263             .addRepeatedDouble(Double.NaN)
264             .addRepeatedDouble(Double.POSITIVE_INFINITY)
265             .addRepeatedDouble(Double.NEGATIVE_INFINITY)
266             .build();
267     assertEquals(
268         "{\n"
269             + "  \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
270             + "  \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
271             + "}",
272         toJsonString(message));
273 
274     assertRoundTripEquals(message);
275   }
276 
testParserAcceptStringForNumericField()277   public void testParserAcceptStringForNumericField() throws Exception {
278     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
279     mergeFromJson(
280         "{\n"
281             + "  \"optionalInt32\": \"1234\",\n"
282             + "  \"optionalUint32\": \"5678\",\n"
283             + "  \"optionalSint32\": \"9012\",\n"
284             + "  \"optionalFixed32\": \"3456\",\n"
285             + "  \"optionalSfixed32\": \"7890\",\n"
286             + "  \"optionalFloat\": \"1.5\",\n"
287             + "  \"optionalDouble\": \"1.25\",\n"
288             + "  \"optionalBool\": \"true\"\n"
289             + "}",
290         builder);
291     TestAllTypes message = builder.build();
292     assertEquals(1234, message.getOptionalInt32());
293     assertEquals(5678, message.getOptionalUint32());
294     assertEquals(9012, message.getOptionalSint32());
295     assertEquals(3456, message.getOptionalFixed32());
296     assertEquals(7890, message.getOptionalSfixed32());
297     assertEquals(1.5f, message.getOptionalFloat(), 0.0f);
298     assertEquals(1.25, message.getOptionalDouble(), 0.0);
299     assertEquals(true, message.getOptionalBool());
300   }
301 
testParserAcceptFloatingPointValueForIntegerField()302   public void testParserAcceptFloatingPointValueForIntegerField() throws Exception {
303     // Test that numeric values like "1.000", "1e5" will also be accepted.
304     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
305     mergeFromJson(
306         "{\n"
307             + "  \"repeatedInt32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
308             + "  \"repeatedUint32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
309             + "  \"repeatedInt64\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
310             + "  \"repeatedUint64\": [1.000, 1e5, \"1.000\", \"1e5\"]\n"
311             + "}",
312         builder);
313     int[] expectedValues = new int[] {1, 100000, 1, 100000};
314     assertEquals(4, builder.getRepeatedInt32Count());
315     assertEquals(4, builder.getRepeatedUint32Count());
316     assertEquals(4, builder.getRepeatedInt64Count());
317     assertEquals(4, builder.getRepeatedUint64Count());
318     for (int i = 0; i < 4; ++i) {
319       assertEquals(expectedValues[i], builder.getRepeatedInt32(i));
320       assertEquals(expectedValues[i], builder.getRepeatedUint32(i));
321       assertEquals(expectedValues[i], builder.getRepeatedInt64(i));
322       assertEquals(expectedValues[i], builder.getRepeatedUint64(i));
323     }
324 
325     // Non-integers will still be rejected.
326     assertRejects("optionalInt32", "1.5");
327     assertRejects("optionalUint32", "1.5");
328     assertRejects("optionalInt64", "1.5");
329     assertRejects("optionalUint64", "1.5");
330   }
331 
assertRejects(String name, String value)332   private void assertRejects(String name, String value) {
333     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
334     try {
335       // Numeric form is rejected.
336       mergeFromJson("{\"" + name + "\":" + value + "}", builder);
337       fail("Exception is expected.");
338     } catch (IOException e) {
339       // Expected.
340     }
341     try {
342       // String form is also rejected.
343       mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
344       fail("Exception is expected.");
345     } catch (IOException e) {
346       // Expected.
347     }
348   }
349 
assertAccepts(String name, String value)350   private void assertAccepts(String name, String value) throws IOException {
351     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
352     // Both numeric form and string form are accepted.
353     mergeFromJson("{\"" + name + "\":" + value + "}", builder);
354     builder.clear();
355     mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
356   }
357 
testParserRejectOutOfRangeNumericValues()358   public void testParserRejectOutOfRangeNumericValues() throws Exception {
359     assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
360     assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
361     assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
362     assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
363 
364     assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
365     assertRejects("optionalUint32", "123456789012345");
366     assertRejects("optionalUint32", "-1");
367 
368     BigInteger one = new BigInteger("1");
369     BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
370     BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
371     assertAccepts("optionalInt64", maxLong.toString());
372     assertAccepts("optionalInt64", minLong.toString());
373     assertRejects("optionalInt64", maxLong.add(one).toString());
374     assertRejects("optionalInt64", minLong.subtract(one).toString());
375 
376     assertAccepts("optionalUint64", maxLong.add(one).toString());
377     assertRejects("optionalUint64", "1234567890123456789012345");
378     assertRejects("optionalUint64", "-1");
379 
380     assertAccepts("optionalBool", "true");
381     assertRejects("optionalBool", "1");
382     assertRejects("optionalBool", "0");
383 
384     assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
385     assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
386     assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
387     assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
388 
389     BigDecimal moreThanOne = new BigDecimal("1.000001");
390     BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
391     BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
392     assertAccepts("optionalDouble", maxDouble.toString());
393     assertAccepts("optionalDouble", minDouble.toString());
394     assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
395     assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
396   }
397 
testParserAcceptNull()398   public void testParserAcceptNull() throws Exception {
399     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
400     mergeFromJson(
401         "{\n"
402             + "  \"optionalInt32\": null,\n"
403             + "  \"optionalInt64\": null,\n"
404             + "  \"optionalUint32\": null,\n"
405             + "  \"optionalUint64\": null,\n"
406             + "  \"optionalSint32\": null,\n"
407             + "  \"optionalSint64\": null,\n"
408             + "  \"optionalFixed32\": null,\n"
409             + "  \"optionalFixed64\": null,\n"
410             + "  \"optionalSfixed32\": null,\n"
411             + "  \"optionalSfixed64\": null,\n"
412             + "  \"optionalFloat\": null,\n"
413             + "  \"optionalDouble\": null,\n"
414             + "  \"optionalBool\": null,\n"
415             + "  \"optionalString\": null,\n"
416             + "  \"optionalBytes\": null,\n"
417             + "  \"optionalNestedMessage\": null,\n"
418             + "  \"optionalNestedEnum\": null,\n"
419             + "  \"repeatedInt32\": null,\n"
420             + "  \"repeatedInt64\": null,\n"
421             + "  \"repeatedUint32\": null,\n"
422             + "  \"repeatedUint64\": null,\n"
423             + "  \"repeatedSint32\": null,\n"
424             + "  \"repeatedSint64\": null,\n"
425             + "  \"repeatedFixed32\": null,\n"
426             + "  \"repeatedFixed64\": null,\n"
427             + "  \"repeatedSfixed32\": null,\n"
428             + "  \"repeatedSfixed64\": null,\n"
429             + "  \"repeatedFloat\": null,\n"
430             + "  \"repeatedDouble\": null,\n"
431             + "  \"repeatedBool\": null,\n"
432             + "  \"repeatedString\": null,\n"
433             + "  \"repeatedBytes\": null,\n"
434             + "  \"repeatedNestedMessage\": null,\n"
435             + "  \"repeatedNestedEnum\": null\n"
436             + "}",
437         builder);
438     TestAllTypes message = builder.build();
439     assertEquals(TestAllTypes.getDefaultInstance(), message);
440 
441     // Repeated field elements cannot be null.
442     try {
443       builder = TestAllTypes.newBuilder();
444       mergeFromJson("{\n" + "  \"repeatedInt32\": [null, null],\n" + "}", builder);
445       fail();
446     } catch (InvalidProtocolBufferException e) {
447       // Exception expected.
448     }
449 
450     try {
451       builder = TestAllTypes.newBuilder();
452       mergeFromJson("{\n" + "  \"repeatedNestedMessage\": [null, null],\n" + "}", builder);
453       fail();
454     } catch (InvalidProtocolBufferException e) {
455       // Exception expected.
456     }
457   }
458 
testNullInOneof()459   public void testNullInOneof() throws Exception {
460     TestOneof.Builder builder = TestOneof.newBuilder();
461     mergeFromJson("{\n" + "  \"oneofNullValue\": null \n" + "}", builder);
462     TestOneof message = builder.build();
463     assertEquals(TestOneof.OneofFieldCase.ONEOF_NULL_VALUE, message.getOneofFieldCase());
464     assertEquals(NullValue.NULL_VALUE, message.getOneofNullValue());
465   }
466 
testNullFirstInDuplicateOneof()467   public void testNullFirstInDuplicateOneof() throws Exception {
468     TestOneof.Builder builder = TestOneof.newBuilder();
469     mergeFromJson("{\"oneofNestedMessage\": null, \"oneofInt32\": 1}", builder);
470     TestOneof message = builder.build();
471     assertEquals(1, message.getOneofInt32());
472   }
473 
testNullLastInDuplicateOneof()474   public void testNullLastInDuplicateOneof() throws Exception {
475     TestOneof.Builder builder = TestOneof.newBuilder();
476     mergeFromJson("{\"oneofInt32\": 1, \"oneofNestedMessage\": null}", builder);
477     TestOneof message = builder.build();
478     assertEquals(1, message.getOneofInt32());
479   }
480 
testParserRejectDuplicatedFields()481   public void testParserRejectDuplicatedFields() throws Exception {
482     // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last
483     // one if multiple entries have the same name. This is not the desired behavior but it can
484     // only be fixed by using our own parser. Here we only test the cases where the names are
485     // different but still referring to the same field.
486 
487     // Duplicated optional fields.
488     try {
489       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
490       mergeFromJson(
491           "{\n"
492               + "  \"optionalNestedMessage\": {},\n"
493               + "  \"optional_nested_message\": {}\n"
494               + "}",
495           builder);
496       fail();
497     } catch (InvalidProtocolBufferException e) {
498       // Exception expected.
499     }
500 
501     // Duplicated repeated fields.
502     try {
503       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
504       mergeFromJson(
505           "{\n"
506               + "  \"repeatedInt32\": [1, 2],\n"
507               + "  \"repeated_int32\": [5, 6]\n"
508               + "}",
509           builder);
510       fail();
511     } catch (InvalidProtocolBufferException e) {
512       // Exception expected.
513     }
514 
515     // Duplicated oneof fields, same name.
516     try {
517       TestOneof.Builder builder = TestOneof.newBuilder();
518       mergeFromJson("{\n" + "  \"oneofInt32\": 1,\n" + "  \"oneof_int32\": 2\n" + "}", builder);
519       fail();
520     } catch (InvalidProtocolBufferException e) {
521       // Exception expected.
522     }
523 
524     // Duplicated oneof fields, different name.
525     try {
526       TestOneof.Builder builder = TestOneof.newBuilder();
527       mergeFromJson(
528           "{\n" + "  \"oneofInt32\": 1,\n" + "  \"oneofNullValue\": null\n" + "}", builder);
529       fail();
530     } catch (InvalidProtocolBufferException e) {
531       // Exception expected.
532     }
533   }
534 
testMapFields()535   public void testMapFields() throws Exception {
536     TestMap.Builder builder = TestMap.newBuilder();
537     builder.putInt32ToInt32Map(1, 10);
538     builder.putInt64ToInt32Map(1234567890123456789L, 10);
539     builder.putUint32ToInt32Map(2, 20);
540     builder.putUint64ToInt32Map(2234567890123456789L, 20);
541     builder.putSint32ToInt32Map(3, 30);
542     builder.putSint64ToInt32Map(3234567890123456789L, 30);
543     builder.putFixed32ToInt32Map(4, 40);
544     builder.putFixed64ToInt32Map(4234567890123456789L, 40);
545     builder.putSfixed32ToInt32Map(5, 50);
546     builder.putSfixed64ToInt32Map(5234567890123456789L, 50);
547     builder.putBoolToInt32Map(false, 6);
548     builder.putStringToInt32Map("Hello", 10);
549 
550     builder.putInt32ToInt64Map(1, 1234567890123456789L);
551     builder.putInt32ToUint32Map(2, 20);
552     builder.putInt32ToUint64Map(2, 2234567890123456789L);
553     builder.putInt32ToSint32Map(3, 30);
554     builder.putInt32ToSint64Map(3, 3234567890123456789L);
555     builder.putInt32ToFixed32Map(4, 40);
556     builder.putInt32ToFixed64Map(4, 4234567890123456789L);
557     builder.putInt32ToSfixed32Map(5, 50);
558     builder.putInt32ToSfixed64Map(5, 5234567890123456789L);
559     builder.putInt32ToFloatMap(6, 1.5f);
560     builder.putInt32ToDoubleMap(6, 1.25);
561     builder.putInt32ToBoolMap(7, false);
562     builder.putInt32ToStringMap(7, "World");
563     builder.putInt32ToBytesMap(8, ByteString.copyFrom(new byte[] {1, 2, 3}));
564     builder.putInt32ToMessageMap(8, NestedMessage.newBuilder().setValue(1234).build());
565     builder.putInt32ToEnumMap(9, NestedEnum.BAR);
566     TestMap message = builder.build();
567 
568     assertEquals(
569         "{\n"
570             + "  \"int32ToInt32Map\": {\n"
571             + "    \"1\": 10\n"
572             + "  },\n"
573             + "  \"int64ToInt32Map\": {\n"
574             + "    \"1234567890123456789\": 10\n"
575             + "  },\n"
576             + "  \"uint32ToInt32Map\": {\n"
577             + "    \"2\": 20\n"
578             + "  },\n"
579             + "  \"uint64ToInt32Map\": {\n"
580             + "    \"2234567890123456789\": 20\n"
581             + "  },\n"
582             + "  \"sint32ToInt32Map\": {\n"
583             + "    \"3\": 30\n"
584             + "  },\n"
585             + "  \"sint64ToInt32Map\": {\n"
586             + "    \"3234567890123456789\": 30\n"
587             + "  },\n"
588             + "  \"fixed32ToInt32Map\": {\n"
589             + "    \"4\": 40\n"
590             + "  },\n"
591             + "  \"fixed64ToInt32Map\": {\n"
592             + "    \"4234567890123456789\": 40\n"
593             + "  },\n"
594             + "  \"sfixed32ToInt32Map\": {\n"
595             + "    \"5\": 50\n"
596             + "  },\n"
597             + "  \"sfixed64ToInt32Map\": {\n"
598             + "    \"5234567890123456789\": 50\n"
599             + "  },\n"
600             + "  \"boolToInt32Map\": {\n"
601             + "    \"false\": 6\n"
602             + "  },\n"
603             + "  \"stringToInt32Map\": {\n"
604             + "    \"Hello\": 10\n"
605             + "  },\n"
606             + "  \"int32ToInt64Map\": {\n"
607             + "    \"1\": \"1234567890123456789\"\n"
608             + "  },\n"
609             + "  \"int32ToUint32Map\": {\n"
610             + "    \"2\": 20\n"
611             + "  },\n"
612             + "  \"int32ToUint64Map\": {\n"
613             + "    \"2\": \"2234567890123456789\"\n"
614             + "  },\n"
615             + "  \"int32ToSint32Map\": {\n"
616             + "    \"3\": 30\n"
617             + "  },\n"
618             + "  \"int32ToSint64Map\": {\n"
619             + "    \"3\": \"3234567890123456789\"\n"
620             + "  },\n"
621             + "  \"int32ToFixed32Map\": {\n"
622             + "    \"4\": 40\n"
623             + "  },\n"
624             + "  \"int32ToFixed64Map\": {\n"
625             + "    \"4\": \"4234567890123456789\"\n"
626             + "  },\n"
627             + "  \"int32ToSfixed32Map\": {\n"
628             + "    \"5\": 50\n"
629             + "  },\n"
630             + "  \"int32ToSfixed64Map\": {\n"
631             + "    \"5\": \"5234567890123456789\"\n"
632             + "  },\n"
633             + "  \"int32ToFloatMap\": {\n"
634             + "    \"6\": 1.5\n"
635             + "  },\n"
636             + "  \"int32ToDoubleMap\": {\n"
637             + "    \"6\": 1.25\n"
638             + "  },\n"
639             + "  \"int32ToBoolMap\": {\n"
640             + "    \"7\": false\n"
641             + "  },\n"
642             + "  \"int32ToStringMap\": {\n"
643             + "    \"7\": \"World\"\n"
644             + "  },\n"
645             + "  \"int32ToBytesMap\": {\n"
646             + "    \"8\": \"AQID\"\n"
647             + "  },\n"
648             + "  \"int32ToMessageMap\": {\n"
649             + "    \"8\": {\n"
650             + "      \"value\": 1234\n"
651             + "    }\n"
652             + "  },\n"
653             + "  \"int32ToEnumMap\": {\n"
654             + "    \"9\": \"BAR\"\n"
655             + "  }\n"
656             + "}",
657         toJsonString(message));
658     assertRoundTripEquals(message);
659 
660     // Test multiple entries.
661     builder = TestMap.newBuilder();
662     builder.putInt32ToInt32Map(1, 2);
663     builder.putInt32ToInt32Map(3, 4);
664     message = builder.build();
665 
666     assertEquals(
667         "{\n" + "  \"int32ToInt32Map\": {\n" + "    \"1\": 2,\n" + "    \"3\": 4\n" + "  }\n" + "}",
668         toJsonString(message));
669     assertRoundTripEquals(message);
670   }
671 
testMapNullValueIsRejected()672   public void testMapNullValueIsRejected() throws Exception {
673     try {
674       TestMap.Builder builder = TestMap.newBuilder();
675       mergeFromJson(
676           "{\n"
677               + "  \"int32ToInt32Map\": {null: 1},\n"
678               + "  \"int32ToMessageMap\": {null: 2}\n"
679               + "}",
680           builder);
681       fail();
682     } catch (InvalidProtocolBufferException e) {
683       // Exception expected.
684     }
685 
686     try {
687       TestMap.Builder builder = TestMap.newBuilder();
688       mergeFromJson(
689           "{\n"
690               + "  \"int32ToInt32Map\": {\"1\": null},\n"
691               + "  \"int32ToMessageMap\": {\"2\": null}\n"
692               + "}",
693           builder);
694       fail();
695 
696     } catch (InvalidProtocolBufferException e) {
697       // Exception expected.
698     }
699   }
700 
testMapEnumNullValueIsIgnored()701   public void testMapEnumNullValueIsIgnored() throws Exception {
702     TestMap.Builder builder = TestMap.newBuilder();
703     mergeFromJsonIgnoringUnknownFields(
704         "{\n" + "  \"int32ToEnumMap\": {\"1\": null}\n" + "}", builder);
705     TestMap map = builder.build();
706     assertEquals(0, map.getInt32ToEnumMapMap().size());
707   }
708 
testParserAcceptNonQuotedObjectKey()709   public void testParserAcceptNonQuotedObjectKey() throws Exception {
710     TestMap.Builder builder = TestMap.newBuilder();
711     mergeFromJson(
712         "{\n" + "  int32ToInt32Map: {1: 2},\n" + "  stringToInt32Map: {hello: 3}\n" + "}", builder);
713     TestMap message = builder.build();
714     assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
715     assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
716   }
717 
testWrappers()718   public void testWrappers() throws Exception {
719     TestWrappers.Builder builder = TestWrappers.newBuilder();
720     builder.getBoolValueBuilder().setValue(false);
721     builder.getInt32ValueBuilder().setValue(0);
722     builder.getInt64ValueBuilder().setValue(0);
723     builder.getUint32ValueBuilder().setValue(0);
724     builder.getUint64ValueBuilder().setValue(0);
725     builder.getFloatValueBuilder().setValue(0.0f);
726     builder.getDoubleValueBuilder().setValue(0.0);
727     builder.getStringValueBuilder().setValue("");
728     builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
729     TestWrappers message = builder.build();
730 
731     assertEquals(
732         "{\n"
733             + "  \"int32Value\": 0,\n"
734             + "  \"uint32Value\": 0,\n"
735             + "  \"int64Value\": \"0\",\n"
736             + "  \"uint64Value\": \"0\",\n"
737             + "  \"floatValue\": 0.0,\n"
738             + "  \"doubleValue\": 0.0,\n"
739             + "  \"boolValue\": false,\n"
740             + "  \"stringValue\": \"\",\n"
741             + "  \"bytesValue\": \"\"\n"
742             + "}",
743         toJsonString(message));
744     assertRoundTripEquals(message);
745 
746     builder = TestWrappers.newBuilder();
747     builder.getBoolValueBuilder().setValue(true);
748     builder.getInt32ValueBuilder().setValue(1);
749     builder.getInt64ValueBuilder().setValue(2);
750     builder.getUint32ValueBuilder().setValue(3);
751     builder.getUint64ValueBuilder().setValue(4);
752     builder.getFloatValueBuilder().setValue(5.0f);
753     builder.getDoubleValueBuilder().setValue(6.0);
754     builder.getStringValueBuilder().setValue("7");
755     builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[] {8}));
756     message = builder.build();
757 
758     assertEquals(
759         "{\n"
760             + "  \"int32Value\": 1,\n"
761             + "  \"uint32Value\": 3,\n"
762             + "  \"int64Value\": \"2\",\n"
763             + "  \"uint64Value\": \"4\",\n"
764             + "  \"floatValue\": 5.0,\n"
765             + "  \"doubleValue\": 6.0,\n"
766             + "  \"boolValue\": true,\n"
767             + "  \"stringValue\": \"7\",\n"
768             + "  \"bytesValue\": \"CA==\"\n"
769             + "}",
770         toJsonString(message));
771     assertRoundTripEquals(message);
772   }
773 
testTimestamp()774   public void testTimestamp() throws Exception {
775     TestTimestamp message =
776         TestTimestamp.newBuilder()
777             .setTimestampValue(Timestamps.parse("1970-01-01T00:00:00Z"))
778             .build();
779 
780     assertEquals(
781         "{\n" + "  \"timestampValue\": \"1970-01-01T00:00:00Z\"\n" + "}", toJsonString(message));
782     assertRoundTripEquals(message);
783   }
784 
testDuration()785   public void testDuration() throws Exception {
786     TestDuration message =
787         TestDuration.newBuilder().setDurationValue(Durations.parse("12345s")).build();
788 
789     assertEquals("{\n" + "  \"durationValue\": \"12345s\"\n" + "}", toJsonString(message));
790     assertRoundTripEquals(message);
791   }
792 
testFieldMask()793   public void testFieldMask() throws Exception {
794     TestFieldMask message =
795         TestFieldMask.newBuilder()
796             .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz,foo_bar.baz"))
797             .build();
798 
799     assertEquals(
800         "{\n" + "  \"fieldMaskValue\": \"foo.bar,baz,fooBar.baz\"\n" + "}", toJsonString(message));
801     assertRoundTripEquals(message);
802   }
803 
testStruct()804   public void testStruct() throws Exception {
805     // Build a struct with all possible values.
806     TestStruct.Builder builder = TestStruct.newBuilder();
807     Struct.Builder structBuilder = builder.getStructValueBuilder();
808     structBuilder.putFields("null_value", Value.newBuilder().setNullValueValue(0).build());
809     structBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1.25).build());
810     structBuilder.putFields("string_value", Value.newBuilder().setStringValue("hello").build());
811     Struct.Builder subStructBuilder = Struct.newBuilder();
812     subStructBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1234).build());
813     structBuilder.putFields(
814         "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
815     ListValue.Builder listBuilder = ListValue.newBuilder();
816     listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
817     listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
818     structBuilder.putFields(
819         "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
820     TestStruct message = builder.build();
821 
822     assertEquals(
823         "{\n"
824             + "  \"structValue\": {\n"
825             + "    \"null_value\": null,\n"
826             + "    \"number_value\": 1.25,\n"
827             + "    \"string_value\": \"hello\",\n"
828             + "    \"struct_value\": {\n"
829             + "      \"number_value\": 1234.0\n"
830             + "    },\n"
831             + "    \"list_value\": [1.125, null]\n"
832             + "  }\n"
833             + "}",
834         toJsonString(message));
835     assertRoundTripEquals(message);
836 
837     builder = TestStruct.newBuilder();
838     builder.setValue(Value.newBuilder().setNullValueValue(0).build());
839     message = builder.build();
840     assertEquals("{\n" + "  \"value\": null\n" + "}", toJsonString(message));
841     assertRoundTripEquals(message);
842 
843     builder = TestStruct.newBuilder();
844     listBuilder = builder.getListValueBuilder();
845     listBuilder.addValues(Value.newBuilder().setNumberValue(31831.125).build());
846     listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
847     message = builder.build();
848     assertEquals("{\n" + "  \"listValue\": [31831.125, null]\n" + "}", toJsonString(message));
849     assertRoundTripEquals(message);
850   }
851 
852 
testAnyFields()853   public void testAnyFields() throws Exception {
854     TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
855     TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
856 
857     // A TypeRegistry must be provided in order to convert Any types.
858     try {
859       toJsonString(message);
860       fail("Exception is expected.");
861     } catch (IOException e) {
862       // Expected.
863     }
864 
865     JsonFormat.TypeRegistry registry =
866         JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
867     JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
868 
869     assertEquals(
870         "{\n"
871             + "  \"anyValue\": {\n"
872             + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
873             + "    \"optionalInt32\": 1234\n"
874             + "  }\n"
875             + "}",
876         printer.print(message));
877     assertRoundTripEquals(message, registry);
878 
879     TestAny messageWithDefaultAnyValue =
880         TestAny.newBuilder().setAnyValue(Any.getDefaultInstance()).build();
881     assertEquals(
882         "{\n"
883             + "  \"anyValue\": {}\n"
884             + "}",
885         printer.print(messageWithDefaultAnyValue));
886     assertRoundTripEquals(messageWithDefaultAnyValue, registry);
887 
888     // Well-known types have a special formatting when embedded in Any.
889     //
890     // 1. Any in Any.
891     Any anyMessage = Any.pack(Any.pack(content));
892     assertEquals(
893         "{\n"
894             + "  \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
895             + "  \"value\": {\n"
896             + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
897             + "    \"optionalInt32\": 1234\n"
898             + "  }\n"
899             + "}",
900         printer.print(anyMessage));
901     assertRoundTripEquals(anyMessage, registry);
902 
903     // 2. Wrappers in Any.
904     anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
905     assertEquals(
906         "{\n"
907             + "  \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
908             + "  \"value\": 12345\n"
909             + "}",
910         printer.print(anyMessage));
911     assertRoundTripEquals(anyMessage, registry);
912     anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
913     assertEquals(
914         "{\n"
915             + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
916             + "  \"value\": 12345\n"
917             + "}",
918         printer.print(anyMessage));
919     assertRoundTripEquals(anyMessage, registry);
920     anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
921     assertEquals(
922         "{\n"
923             + "  \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
924             + "  \"value\": \"12345\"\n"
925             + "}",
926         printer.print(anyMessage));
927     assertRoundTripEquals(anyMessage, registry);
928     anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
929     assertEquals(
930         "{\n"
931             + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
932             + "  \"value\": \"12345\"\n"
933             + "}",
934         printer.print(anyMessage));
935     assertRoundTripEquals(anyMessage, registry);
936     anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
937     assertEquals(
938         "{\n"
939             + "  \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
940             + "  \"value\": 12345.0\n"
941             + "}",
942         printer.print(anyMessage));
943     assertRoundTripEquals(anyMessage, registry);
944     anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
945     assertEquals(
946         "{\n"
947             + "  \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
948             + "  \"value\": 12345.0\n"
949             + "}",
950         printer.print(anyMessage));
951     assertRoundTripEquals(anyMessage, registry);
952     anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
953     assertEquals(
954         "{\n"
955             + "  \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
956             + "  \"value\": true\n"
957             + "}",
958         printer.print(anyMessage));
959     assertRoundTripEquals(anyMessage, registry);
960     anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
961     assertEquals(
962         "{\n"
963             + "  \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
964             + "  \"value\": \"Hello\"\n"
965             + "}",
966         printer.print(anyMessage));
967     assertRoundTripEquals(anyMessage, registry);
968     anyMessage =
969         Any.pack(BytesValue.newBuilder().setValue(ByteString.copyFrom(new byte[] {1, 2})).build());
970     assertEquals(
971         "{\n"
972             + "  \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
973             + "  \"value\": \"AQI=\"\n"
974             + "}",
975         printer.print(anyMessage));
976     assertRoundTripEquals(anyMessage, registry);
977 
978     // 3. Timestamp in Any.
979     anyMessage = Any.pack(Timestamps.parse("1969-12-31T23:59:59Z"));
980     assertEquals(
981         "{\n"
982             + "  \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
983             + "  \"value\": \"1969-12-31T23:59:59Z\"\n"
984             + "}",
985         printer.print(anyMessage));
986     assertRoundTripEquals(anyMessage, registry);
987 
988     // 4. Duration in Any
989     anyMessage = Any.pack(Durations.parse("12345.10s"));
990     assertEquals(
991         "{\n"
992             + "  \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
993             + "  \"value\": \"12345.100s\"\n"
994             + "}",
995         printer.print(anyMessage));
996     assertRoundTripEquals(anyMessage, registry);
997 
998     // 5. FieldMask in Any
999     anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
1000     assertEquals(
1001         "{\n"
1002             + "  \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
1003             + "  \"value\": \"foo.bar,baz\"\n"
1004             + "}",
1005         printer.print(anyMessage));
1006     assertRoundTripEquals(anyMessage, registry);
1007 
1008     // 6. Struct in Any
1009     Struct.Builder structBuilder = Struct.newBuilder();
1010     structBuilder.putFields("number", Value.newBuilder().setNumberValue(1.125).build());
1011     anyMessage = Any.pack(structBuilder.build());
1012     assertEquals(
1013         "{\n"
1014             + "  \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
1015             + "  \"value\": {\n"
1016             + "    \"number\": 1.125\n"
1017             + "  }\n"
1018             + "}",
1019         printer.print(anyMessage));
1020     assertRoundTripEquals(anyMessage, registry);
1021 
1022     // 7. Value (number type) in Any
1023     Value.Builder valueBuilder = Value.newBuilder();
1024     valueBuilder.setNumberValue(1);
1025     anyMessage = Any.pack(valueBuilder.build());
1026     assertEquals(
1027         "{\n"
1028             + "  \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
1029             + "  \"value\": 1.0\n"
1030             + "}",
1031         printer.print(anyMessage));
1032     assertRoundTripEquals(anyMessage, registry);
1033 
1034     // 8. Value (null type) in Any
1035     anyMessage = Any.pack(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build());
1036     assertEquals(
1037         "{\n"
1038             + "  \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
1039             + "  \"value\": null\n"
1040             + "}",
1041         printer.print(anyMessage));
1042     assertRoundTripEquals(anyMessage, registry);
1043   }
1044 
testAnyInMaps()1045   public void testAnyInMaps() throws Exception {
1046     JsonFormat.TypeRegistry registry =
1047         JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
1048     JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
1049 
1050     TestAny.Builder testAny = TestAny.newBuilder();
1051     testAny.putAnyMap("int32_wrapper", Any.pack(Int32Value.newBuilder().setValue(123).build()));
1052     testAny.putAnyMap("int64_wrapper", Any.pack(Int64Value.newBuilder().setValue(456).build()));
1053     testAny.putAnyMap("timestamp", Any.pack(Timestamps.parse("1969-12-31T23:59:59Z")));
1054     testAny.putAnyMap("duration", Any.pack(Durations.parse("12345.1s")));
1055     testAny.putAnyMap("field_mask", Any.pack(FieldMaskUtil.fromString("foo.bar,baz")));
1056     Value numberValue = Value.newBuilder().setNumberValue(1.125).build();
1057     Struct.Builder struct = Struct.newBuilder();
1058     struct.putFields("number", numberValue);
1059     testAny.putAnyMap("struct", Any.pack(struct.build()));
1060     Value nullValue = Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build();
1061     testAny.putAnyMap(
1062         "list_value",
1063         Any.pack(ListValue.newBuilder().addValues(numberValue).addValues(nullValue).build()));
1064     testAny.putAnyMap("number_value", Any.pack(numberValue));
1065     testAny.putAnyMap("any_value_number", Any.pack(Any.pack(numberValue)));
1066     testAny.putAnyMap("any_value_default", Any.pack(Any.getDefaultInstance()));
1067     testAny.putAnyMap("default", Any.getDefaultInstance());
1068 
1069     assertEquals(
1070         "{\n"
1071             + "  \"anyMap\": {\n"
1072             + "    \"int32_wrapper\": {\n"
1073             + "      \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
1074             + "      \"value\": 123\n"
1075             + "    },\n"
1076             + "    \"int64_wrapper\": {\n"
1077             + "      \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
1078             + "      \"value\": \"456\"\n"
1079             + "    },\n"
1080             + "    \"timestamp\": {\n"
1081             + "      \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
1082             + "      \"value\": \"1969-12-31T23:59:59Z\"\n"
1083             + "    },\n"
1084             + "    \"duration\": {\n"
1085             + "      \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
1086             + "      \"value\": \"12345.100s\"\n"
1087             + "    },\n"
1088             + "    \"field_mask\": {\n"
1089             + "      \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
1090             + "      \"value\": \"foo.bar,baz\"\n"
1091             + "    },\n"
1092             + "    \"struct\": {\n"
1093             + "      \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
1094             + "      \"value\": {\n"
1095             + "        \"number\": 1.125\n"
1096             + "      }\n"
1097             + "    },\n"
1098             + "    \"list_value\": {\n"
1099             + "      \"@type\": \"type.googleapis.com/google.protobuf.ListValue\",\n"
1100             + "      \"value\": [1.125, null]\n"
1101             + "    },\n"
1102             + "    \"number_value\": {\n"
1103             + "      \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
1104             + "      \"value\": 1.125\n"
1105             + "    },\n"
1106             + "    \"any_value_number\": {\n"
1107             + "      \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
1108             + "      \"value\": {\n"
1109             + "        \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
1110             + "        \"value\": 1.125\n"
1111             + "      }\n"
1112             + "    },\n"
1113             + "    \"any_value_default\": {\n"
1114             + "      \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
1115             + "      \"value\": {}\n"
1116             + "    },\n"
1117             + "    \"default\": {}\n"
1118             + "  }\n"
1119             + "}",
1120         printer.print(testAny.build()));
1121     assertRoundTripEquals(testAny.build(), registry);
1122   }
1123 
testParserMissingTypeUrl()1124   public void testParserMissingTypeUrl() throws Exception {
1125     try {
1126       Any.Builder builder = Any.newBuilder();
1127       mergeFromJson("{\n" + "  \"optionalInt32\": 1234\n" + "}", builder);
1128       fail("Exception is expected.");
1129     } catch (IOException e) {
1130       // Expected.
1131     }
1132   }
1133 
testParserUnexpectedTypeUrl()1134   public void testParserUnexpectedTypeUrl() throws Exception {
1135     try {
1136       Any.Builder builder = Any.newBuilder();
1137       mergeFromJson(
1138           "{\n"
1139               + "  \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
1140               + "  \"optionalInt32\": 12345\n"
1141               + "}",
1142           builder);
1143       fail("Exception is expected.");
1144     } catch (IOException e) {
1145       // Expected.
1146     }
1147   }
1148 
testParserRejectTrailingComma()1149   public void testParserRejectTrailingComma() throws Exception {
1150     try {
1151       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1152       mergeFromJson("{\n" + "  \"optionalInt32\": 12345,\n" + "}", builder);
1153       fail("Exception is expected.");
1154     } catch (IOException e) {
1155       // Expected.
1156     }
1157 
1158     // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
1159     // the JsonReader to non-lenient mode. If we want to enforce strict JSON
1160     // compliance, we might want to switch to a different JSON parser or
1161     // implement one by ourselves.
1162     // try {
1163     //   TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1164     //   JsonFormat.merge(
1165     //       "{\n"
1166     //       + "  \"repeatedInt32\": [12345,]\n"
1167     //       + "}", builder);
1168     //   fail("Exception is expected.");
1169     // } catch (IOException e) {
1170     //   // Expected.
1171     // }
1172   }
1173 
testParserRejectInvalidBase64()1174   public void testParserRejectInvalidBase64() throws Exception {
1175     assertRejects("optionalBytes", "!@#$");
1176   }
1177 
testParserAcceptBase64Variants()1178   public void testParserAcceptBase64Variants() throws Exception {
1179     assertAccepts("optionalBytes", "AQI"); // No padding
1180     assertAccepts("optionalBytes", "-_w"); // base64Url, no padding
1181   }
1182 
testParserRejectInvalidEnumValue()1183   public void testParserRejectInvalidEnumValue() throws Exception {
1184     try {
1185       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1186       mergeFromJson("{\n" + "  \"optionalNestedEnum\": \"XXX\"\n" + "}", builder);
1187       fail("Exception is expected.");
1188     } catch (InvalidProtocolBufferException e) {
1189       // Expected.
1190     }
1191   }
1192 
testParserUnknownFields()1193   public void testParserUnknownFields() throws Exception {
1194     try {
1195       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1196       String json = "{\n" + "  \"unknownField\": \"XXX\"\n" + "}";
1197       JsonFormat.parser().merge(json, builder);
1198       fail("Exception is expected.");
1199     } catch (InvalidProtocolBufferException e) {
1200       // Expected.
1201     }
1202   }
1203 
testParserIgnoringUnknownFields()1204   public void testParserIgnoringUnknownFields() throws Exception {
1205     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1206     String json = "{\n" + "  \"unknownField\": \"XXX\"\n" + "}";
1207     JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
1208   }
1209 
testParserIgnoringUnknownEnums()1210   public void testParserIgnoringUnknownEnums() throws Exception {
1211     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1212     String json = "{\n" + "  \"optionalNestedEnum\": \"XXX\"\n" + "}";
1213     JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
1214     assertEquals(0, builder.getOptionalNestedEnumValue());
1215   }
1216 
testParserSupportAliasEnums()1217   public void testParserSupportAliasEnums() throws Exception {
1218     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1219     String json = "{\n" + "  \"optionalAliasedEnum\": \"QUX\"\n" + "}";
1220     JsonFormat.parser().merge(json, builder);
1221     assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
1222 
1223     builder = TestAllTypes.newBuilder();
1224     json = "{\n" + "  \"optionalAliasedEnum\": \"qux\"\n" + "}";
1225     JsonFormat.parser().merge(json, builder);
1226     assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
1227 
1228     builder = TestAllTypes.newBuilder();
1229     json = "{\n" + "  \"optionalAliasedEnum\": \"bAz\"\n" + "}";
1230     JsonFormat.parser().merge(json, builder);
1231     assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
1232   }
1233 
testUnknownEnumMap()1234   public void testUnknownEnumMap() throws Exception {
1235     TestMap.Builder builder = TestMap.newBuilder();
1236     JsonFormat.parser()
1237         .ignoringUnknownFields()
1238         .merge("{\n" + "  \"int32ToEnumMap\": {1: XXX, 2: FOO}" + "}", builder);
1239 
1240     assertEquals(NestedEnum.FOO, builder.getInt32ToEnumMapMap().get(2));
1241     assertEquals(1, builder.getInt32ToEnumMapMap().size());
1242   }
1243 
testRepeatedUnknownEnum()1244   public void testRepeatedUnknownEnum() throws Exception {
1245     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1246     JsonFormat.parser()
1247         .ignoringUnknownFields()
1248         .merge("{\n" + "  \"repeatedNestedEnum\": [XXX, FOO, BAR, BAZ]" + "}", builder);
1249 
1250     assertEquals(NestedEnum.FOO, builder.getRepeatedNestedEnum(0));
1251     assertEquals(NestedEnum.BAR, builder.getRepeatedNestedEnum(1));
1252     assertEquals(NestedEnum.BAZ, builder.getRepeatedNestedEnum(2));
1253     assertEquals(3, builder.getRepeatedNestedEnumList().size());
1254   }
1255 
testParserIntegerEnumValue()1256   public void testParserIntegerEnumValue() throws Exception {
1257     TestAllTypes.Builder actualBuilder = TestAllTypes.newBuilder();
1258     mergeFromJson("{\n" + "  \"optionalNestedEnum\": 2\n" + "}", actualBuilder);
1259 
1260     TestAllTypes expected = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAZ).build();
1261     assertEquals(expected, actualBuilder.build());
1262   }
1263 
testCustomJsonName()1264   public void testCustomJsonName() throws Exception {
1265     TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
1266     assertEquals("{\n" + "  \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
1267     assertRoundTripEquals(message);
1268   }
1269 
1270   // Regression test for b/73832901. Make sure html tags are escaped.
testHtmlEscape()1271   public void testHtmlEscape() throws Exception {
1272     TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("</script>").build();
1273     assertEquals("{\n  \"optionalString\": \"\\u003c/script\\u003e\"\n}", toJsonString(message));
1274 
1275     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1276     JsonFormat.parser().merge(toJsonString(message), builder);
1277     assertEquals(message.getOptionalString(), builder.getOptionalString());
1278   }
1279 
testIncludingDefaultValueFields()1280   public void testIncludingDefaultValueFields() throws Exception {
1281     TestAllTypes message = TestAllTypes.getDefaultInstance();
1282     assertEquals("{\n}", JsonFormat.printer().print(message));
1283     assertEquals(
1284         "{\n"
1285             + "  \"optionalInt32\": 0,\n"
1286             + "  \"optionalInt64\": \"0\",\n"
1287             + "  \"optionalUint32\": 0,\n"
1288             + "  \"optionalUint64\": \"0\",\n"
1289             + "  \"optionalSint32\": 0,\n"
1290             + "  \"optionalSint64\": \"0\",\n"
1291             + "  \"optionalFixed32\": 0,\n"
1292             + "  \"optionalFixed64\": \"0\",\n"
1293             + "  \"optionalSfixed32\": 0,\n"
1294             + "  \"optionalSfixed64\": \"0\",\n"
1295             + "  \"optionalFloat\": 0.0,\n"
1296             + "  \"optionalDouble\": 0.0,\n"
1297             + "  \"optionalBool\": false,\n"
1298             + "  \"optionalString\": \"\",\n"
1299             + "  \"optionalBytes\": \"\",\n"
1300             + "  \"optionalNestedEnum\": \"FOO\",\n"
1301             + "  \"repeatedInt32\": [],\n"
1302             + "  \"repeatedInt64\": [],\n"
1303             + "  \"repeatedUint32\": [],\n"
1304             + "  \"repeatedUint64\": [],\n"
1305             + "  \"repeatedSint32\": [],\n"
1306             + "  \"repeatedSint64\": [],\n"
1307             + "  \"repeatedFixed32\": [],\n"
1308             + "  \"repeatedFixed64\": [],\n"
1309             + "  \"repeatedSfixed32\": [],\n"
1310             + "  \"repeatedSfixed64\": [],\n"
1311             + "  \"repeatedFloat\": [],\n"
1312             + "  \"repeatedDouble\": [],\n"
1313             + "  \"repeatedBool\": [],\n"
1314             + "  \"repeatedString\": [],\n"
1315             + "  \"repeatedBytes\": [],\n"
1316             + "  \"repeatedNestedMessage\": [],\n"
1317             + "  \"repeatedNestedEnum\": [],\n"
1318             + "  \"optionalAliasedEnum\": \"ALIAS_FOO\"\n"
1319             + "}",
1320         JsonFormat.printer().includingDefaultValueFields().print(message));
1321 
1322     Set<FieldDescriptor> fixedFields = new HashSet<FieldDescriptor>();
1323     for (FieldDescriptor fieldDesc : TestAllTypes.getDescriptor().getFields()) {
1324       if (fieldDesc.getName().contains("_fixed")) {
1325         fixedFields.add(fieldDesc);
1326       }
1327     }
1328 
1329     assertEquals(
1330         "{\n"
1331             + "  \"optionalFixed32\": 0,\n"
1332             + "  \"optionalFixed64\": \"0\",\n"
1333             + "  \"repeatedFixed32\": [],\n"
1334             + "  \"repeatedFixed64\": []\n"
1335             + "}",
1336         JsonFormat.printer().includingDefaultValueFields(fixedFields).print(message));
1337 
1338     TestAllTypes messageNonDefaults =
1339         message.toBuilder().setOptionalInt64(1234).setOptionalFixed32(3232).build();
1340     assertEquals(
1341         "{\n"
1342             + "  \"optionalInt64\": \"1234\",\n"
1343             + "  \"optionalFixed32\": 3232,\n"
1344             + "  \"optionalFixed64\": \"0\",\n"
1345             + "  \"repeatedFixed32\": [],\n"
1346             + "  \"repeatedFixed64\": []\n"
1347             + "}",
1348         JsonFormat.printer().includingDefaultValueFields(fixedFields).print(messageNonDefaults));
1349 
1350     try {
1351       JsonFormat.printer().includingDefaultValueFields().includingDefaultValueFields();
1352       fail("IllegalStateException is expected.");
1353     } catch (IllegalStateException e) {
1354       // Expected.
1355       assertTrue(
1356           "Exception message should mention includingDefaultValueFields.",
1357           e.getMessage().contains("includingDefaultValueFields"));
1358     }
1359 
1360     try {
1361       JsonFormat.printer().includingDefaultValueFields().includingDefaultValueFields(fixedFields);
1362       fail("IllegalStateException is expected.");
1363     } catch (IllegalStateException e) {
1364       // Expected.
1365       assertTrue(
1366           "Exception message should mention includingDefaultValueFields.",
1367           e.getMessage().contains("includingDefaultValueFields"));
1368     }
1369 
1370     try {
1371       JsonFormat.printer().includingDefaultValueFields(fixedFields).includingDefaultValueFields();
1372       fail("IllegalStateException is expected.");
1373     } catch (IllegalStateException e) {
1374       // Expected.
1375       assertTrue(
1376           "Exception message should mention includingDefaultValueFields.",
1377           e.getMessage().contains("includingDefaultValueFields"));
1378     }
1379 
1380     try {
1381       JsonFormat.printer()
1382           .includingDefaultValueFields(fixedFields)
1383           .includingDefaultValueFields(fixedFields);
1384       fail("IllegalStateException is expected.");
1385     } catch (IllegalStateException e) {
1386       // Expected.
1387       assertTrue(
1388           "Exception message should mention includingDefaultValueFields.",
1389           e.getMessage().contains("includingDefaultValueFields"));
1390     }
1391 
1392     Set<FieldDescriptor> intFields = new HashSet<FieldDescriptor>();
1393     for (FieldDescriptor fieldDesc : TestAllTypes.getDescriptor().getFields()) {
1394       if (fieldDesc.getName().contains("_int")) {
1395         intFields.add(fieldDesc);
1396       }
1397     }
1398 
1399     try {
1400       JsonFormat.printer()
1401           .includingDefaultValueFields(intFields)
1402           .includingDefaultValueFields(fixedFields);
1403       fail("IllegalStateException is expected.");
1404     } catch (IllegalStateException e) {
1405       // Expected.
1406       assertTrue(
1407           "Exception message should mention includingDefaultValueFields.",
1408           e.getMessage().contains("includingDefaultValueFields"));
1409     }
1410 
1411     try {
1412       JsonFormat.printer().includingDefaultValueFields(null);
1413       fail("IllegalArgumentException is expected.");
1414     } catch (IllegalArgumentException e) {
1415       // Expected.
1416       assertTrue(
1417           "Exception message should mention includingDefaultValueFields.",
1418           e.getMessage().contains("includingDefaultValueFields"));
1419     }
1420 
1421     try {
1422       JsonFormat.printer().includingDefaultValueFields(Collections.<FieldDescriptor>emptySet());
1423       fail("IllegalArgumentException is expected.");
1424     } catch (IllegalArgumentException e) {
1425       // Expected.
1426       assertTrue(
1427           "Exception message should mention includingDefaultValueFields.",
1428           e.getMessage().contains("includingDefaultValueFields"));
1429     }
1430 
1431     TestMap mapMessage = TestMap.getDefaultInstance();
1432     assertEquals("{\n}", JsonFormat.printer().print(mapMessage));
1433     assertEquals(
1434         "{\n"
1435             + "  \"int32ToInt32Map\": {\n"
1436             + "  },\n"
1437             + "  \"int64ToInt32Map\": {\n"
1438             + "  },\n"
1439             + "  \"uint32ToInt32Map\": {\n"
1440             + "  },\n"
1441             + "  \"uint64ToInt32Map\": {\n"
1442             + "  },\n"
1443             + "  \"sint32ToInt32Map\": {\n"
1444             + "  },\n"
1445             + "  \"sint64ToInt32Map\": {\n"
1446             + "  },\n"
1447             + "  \"fixed32ToInt32Map\": {\n"
1448             + "  },\n"
1449             + "  \"fixed64ToInt32Map\": {\n"
1450             + "  },\n"
1451             + "  \"sfixed32ToInt32Map\": {\n"
1452             + "  },\n"
1453             + "  \"sfixed64ToInt32Map\": {\n"
1454             + "  },\n"
1455             + "  \"boolToInt32Map\": {\n"
1456             + "  },\n"
1457             + "  \"stringToInt32Map\": {\n"
1458             + "  },\n"
1459             + "  \"int32ToInt64Map\": {\n"
1460             + "  },\n"
1461             + "  \"int32ToUint32Map\": {\n"
1462             + "  },\n"
1463             + "  \"int32ToUint64Map\": {\n"
1464             + "  },\n"
1465             + "  \"int32ToSint32Map\": {\n"
1466             + "  },\n"
1467             + "  \"int32ToSint64Map\": {\n"
1468             + "  },\n"
1469             + "  \"int32ToFixed32Map\": {\n"
1470             + "  },\n"
1471             + "  \"int32ToFixed64Map\": {\n"
1472             + "  },\n"
1473             + "  \"int32ToSfixed32Map\": {\n"
1474             + "  },\n"
1475             + "  \"int32ToSfixed64Map\": {\n"
1476             + "  },\n"
1477             + "  \"int32ToFloatMap\": {\n"
1478             + "  },\n"
1479             + "  \"int32ToDoubleMap\": {\n"
1480             + "  },\n"
1481             + "  \"int32ToBoolMap\": {\n"
1482             + "  },\n"
1483             + "  \"int32ToStringMap\": {\n"
1484             + "  },\n"
1485             + "  \"int32ToBytesMap\": {\n"
1486             + "  },\n"
1487             + "  \"int32ToMessageMap\": {\n"
1488             + "  },\n"
1489             + "  \"int32ToEnumMap\": {\n"
1490             + "  }\n"
1491             + "}",
1492         JsonFormat.printer().includingDefaultValueFields().print(mapMessage));
1493 
1494     TestOneof oneofMessage = TestOneof.getDefaultInstance();
1495     assertEquals("{\n}", JsonFormat.printer().print(oneofMessage));
1496     assertEquals("{\n}", JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
1497 
1498     oneofMessage = TestOneof.newBuilder().setOneofInt32(42).build();
1499     assertEquals("{\n  \"oneofInt32\": 42\n}", JsonFormat.printer().print(oneofMessage));
1500     assertEquals(
1501         "{\n  \"oneofInt32\": 42\n}",
1502         JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
1503 
1504     TestOneof.Builder oneofBuilder = TestOneof.newBuilder();
1505     mergeFromJson("{\n" + "  \"oneofNullValue\": null \n" + "}", oneofBuilder);
1506     oneofMessage = oneofBuilder.build();
1507     assertEquals("{\n  \"oneofNullValue\": null\n}", JsonFormat.printer().print(oneofMessage));
1508     assertEquals(
1509         "{\n  \"oneofNullValue\": null\n}",
1510         JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
1511   }
1512 
testPreservingProtoFieldNames()1513   public void testPreservingProtoFieldNames() throws Exception {
1514     TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
1515     assertEquals("{\n" + "  \"optionalInt32\": 12345\n" + "}", JsonFormat.printer().print(message));
1516     assertEquals(
1517         "{\n" + "  \"optional_int32\": 12345\n" + "}",
1518         JsonFormat.printer().preservingProtoFieldNames().print(message));
1519 
1520     // The json_name field option is ignored when configured to use original proto field names.
1521     TestCustomJsonName messageWithCustomJsonName =
1522         TestCustomJsonName.newBuilder().setValue(12345).build();
1523     assertEquals(
1524         "{\n" + "  \"value\": 12345\n" + "}",
1525         JsonFormat.printer().preservingProtoFieldNames().print(messageWithCustomJsonName));
1526 
1527     // Parsers accept both original proto field names and lowerCamelCase names.
1528     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1529     JsonFormat.parser().merge("{\"optionalInt32\": 12345}", builder);
1530     assertEquals(12345, builder.getOptionalInt32());
1531     builder.clear();
1532     JsonFormat.parser().merge("{\"optional_int32\": 54321}", builder);
1533     assertEquals(54321, builder.getOptionalInt32());
1534   }
1535 
testPrintingEnumsAsInts()1536   public void testPrintingEnumsAsInts() throws Exception {
1537     TestAllTypes message = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAR).build();
1538     assertEquals(
1539         "{\n" + "  \"optionalNestedEnum\": 1\n" + "}",
1540         JsonFormat.printer().printingEnumsAsInts().print(message));
1541   }
1542 
testOmittingInsignificantWhiteSpace()1543   public void testOmittingInsignificantWhiteSpace() throws Exception {
1544     TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
1545     assertEquals(
1546         "{" + "\"optionalInt32\":12345" + "}",
1547         JsonFormat.printer().omittingInsignificantWhitespace().print(message));
1548     TestAllTypes message1 = TestAllTypes.getDefaultInstance();
1549     assertEquals("{}", JsonFormat.printer().omittingInsignificantWhitespace().print(message1));
1550     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1551     setAllFields(builder);
1552     TestAllTypes message2 = builder.build();
1553     assertEquals(
1554         "{"
1555             + "\"optionalInt32\":1234,"
1556             + "\"optionalInt64\":\"1234567890123456789\","
1557             + "\"optionalUint32\":5678,"
1558             + "\"optionalUint64\":\"2345678901234567890\","
1559             + "\"optionalSint32\":9012,"
1560             + "\"optionalSint64\":\"3456789012345678901\","
1561             + "\"optionalFixed32\":3456,"
1562             + "\"optionalFixed64\":\"4567890123456789012\","
1563             + "\"optionalSfixed32\":7890,"
1564             + "\"optionalSfixed64\":\"5678901234567890123\","
1565             + "\"optionalFloat\":1.5,"
1566             + "\"optionalDouble\":1.25,"
1567             + "\"optionalBool\":true,"
1568             + "\"optionalString\":\"Hello world!\","
1569             + "\"optionalBytes\":\"AAEC\","
1570             + "\"optionalNestedMessage\":{"
1571             + "\"value\":100"
1572             + "},"
1573             + "\"optionalNestedEnum\":\"BAR\","
1574             + "\"repeatedInt32\":[1234,234],"
1575             + "\"repeatedInt64\":[\"1234567890123456789\",\"234567890123456789\"],"
1576             + "\"repeatedUint32\":[5678,678],"
1577             + "\"repeatedUint64\":[\"2345678901234567890\",\"345678901234567890\"],"
1578             + "\"repeatedSint32\":[9012,10],"
1579             + "\"repeatedSint64\":[\"3456789012345678901\",\"456789012345678901\"],"
1580             + "\"repeatedFixed32\":[3456,456],"
1581             + "\"repeatedFixed64\":[\"4567890123456789012\",\"567890123456789012\"],"
1582             + "\"repeatedSfixed32\":[7890,890],"
1583             + "\"repeatedSfixed64\":[\"5678901234567890123\",\"678901234567890123\"],"
1584             + "\"repeatedFloat\":[1.5,11.5],"
1585             + "\"repeatedDouble\":[1.25,11.25],"
1586             + "\"repeatedBool\":[true,true],"
1587             + "\"repeatedString\":[\"Hello world!\",\"ello world!\"],"
1588             + "\"repeatedBytes\":[\"AAEC\",\"AQI=\"],"
1589             + "\"repeatedNestedMessage\":[{"
1590             + "\"value\":100"
1591             + "},{"
1592             + "\"value\":200"
1593             + "}],"
1594             + "\"repeatedNestedEnum\":[\"BAR\",\"BAZ\"]"
1595             + "}",
1596         toCompactJsonString(message2));
1597   }
1598 
1599   // Regression test for b/29892357
testEmptyWrapperTypesInAny()1600   public void testEmptyWrapperTypesInAny() throws Exception {
1601     JsonFormat.TypeRegistry registry =
1602         JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
1603     JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
1604 
1605     Any.Builder builder = Any.newBuilder();
1606     parser.merge(
1607         "{\n"
1608             + "  \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
1609             + "  \"value\": false\n"
1610             + "}\n",
1611         builder);
1612     Any any = builder.build();
1613     assertEquals(0, any.getValue().size());
1614   }
1615 
testRecursionLimit()1616   public void testRecursionLimit() throws Exception {
1617     String input =
1618         "{\n"
1619             + "  \"nested\": {\n"
1620             + "    \"nested\": {\n"
1621             + "      \"nested\": {\n"
1622             + "        \"nested\": {\n"
1623             + "          \"value\": 1234\n"
1624             + "        }\n"
1625             + "      }\n"
1626             + "    }\n"
1627             + "  }\n"
1628             + "}\n";
1629 
1630     JsonFormat.Parser parser = JsonFormat.parser();
1631     TestRecursive.Builder builder = TestRecursive.newBuilder();
1632     parser.merge(input, builder);
1633     TestRecursive message = builder.build();
1634     assertEquals(1234, message.getNested().getNested().getNested().getNested().getValue());
1635 
1636     parser = JsonFormat.parser().usingRecursionLimit(3);
1637     builder = TestRecursive.newBuilder();
1638     try {
1639       parser.merge(input, builder);
1640       fail("Exception is expected.");
1641     } catch (InvalidProtocolBufferException e) {
1642       // Expected.
1643     }
1644   }
1645 
1646   // Test that we are not leaking out JSON exceptions.
testJsonException()1647   public void testJsonException() throws Exception {
1648     InputStream throwingInputStream =
1649         new InputStream() {
1650           public int read() throws IOException {
1651             throw new IOException("12345");
1652           }
1653         };
1654     InputStreamReader throwingReader = new InputStreamReader(throwingInputStream);
1655     // When the underlying reader throws IOException, JsonFormat should forward
1656     // through this IOException.
1657     try {
1658       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1659       JsonFormat.parser().merge(throwingReader, builder);
1660       fail("Exception is expected.");
1661     } catch (IOException e) {
1662       assertEquals("12345", e.getMessage());
1663     }
1664 
1665     Reader invalidJsonReader = new StringReader("{ xxx - yyy }");
1666     // When the JSON parser throws parser exceptions, JsonFormat should turn
1667     // that into InvalidProtocolBufferException.
1668     try {
1669       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1670       JsonFormat.parser().merge(invalidJsonReader, builder);
1671       fail("Exception is expected.");
1672     } catch (InvalidProtocolBufferException e) {
1673       // Expected.
1674     }
1675   }
1676 
testSortedMapKeys()1677   public void testSortedMapKeys() throws Exception {
1678     TestMap.Builder mapBuilder = TestMap.newBuilder();
1679     mapBuilder.putStringToInt32Map("\ud834\udd20", 3); // utf-8 F0 9D 84 A0
1680     mapBuilder.putStringToInt32Map("foo", 99);
1681     mapBuilder.putStringToInt32Map("xxx", 123);
1682     mapBuilder.putStringToInt32Map("\u20ac", 1); // utf-8 E2 82 AC
1683     mapBuilder.putStringToInt32Map("abc", 20);
1684     mapBuilder.putStringToInt32Map("19", 19);
1685     mapBuilder.putStringToInt32Map("8", 8);
1686     mapBuilder.putStringToInt32Map("\ufb00", 2); // utf-8 EF AC 80
1687     mapBuilder.putInt32ToInt32Map(3, 3);
1688     mapBuilder.putInt32ToInt32Map(10, 10);
1689     mapBuilder.putInt32ToInt32Map(5, 5);
1690     mapBuilder.putInt32ToInt32Map(4, 4);
1691     mapBuilder.putInt32ToInt32Map(1, 1);
1692     mapBuilder.putInt32ToInt32Map(2, 2);
1693     mapBuilder.putInt32ToInt32Map(-3, -3);
1694     TestMap mapMessage = mapBuilder.build();
1695     assertEquals(
1696         "{\n"
1697             + "  \"int32ToInt32Map\": {\n"
1698             + "    \"-3\": -3,\n"
1699             + "    \"1\": 1,\n"
1700             + "    \"2\": 2,\n"
1701             + "    \"3\": 3,\n"
1702             + "    \"4\": 4,\n"
1703             + "    \"5\": 5,\n"
1704             + "    \"10\": 10\n"
1705             + "  },\n"
1706             + "  \"stringToInt32Map\": {\n"
1707             + "    \"19\": 19,\n"
1708             + "    \"8\": 8,\n"
1709             + "    \"abc\": 20,\n"
1710             + "    \"foo\": 99,\n"
1711             + "    \"xxx\": 123,\n"
1712             + "    \"\u20ac\": 1,\n"
1713             + "    \"\ufb00\": 2,\n"
1714             + "    \"\ud834\udd20\": 3\n"
1715             + "  }\n"
1716             + "}",
1717         toSortedJsonString(mapMessage));
1718 
1719     TestMap emptyMap = TestMap.getDefaultInstance();
1720     assertEquals("{\n}", toSortedJsonString(emptyMap));
1721   }
1722 }
1723