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.DoubleValue;
38 import com.google.protobuf.FloatValue;
39 import com.google.protobuf.Int32Value;
40 import com.google.protobuf.Int64Value;
41 import com.google.protobuf.InvalidProtocolBufferException;
42 import com.google.protobuf.ListValue;
43 import com.google.protobuf.Message;
44 import com.google.protobuf.NullValue;
45 import com.google.protobuf.StringValue;
46 import com.google.protobuf.Struct;
47 import com.google.protobuf.UInt32Value;
48 import com.google.protobuf.UInt64Value;
49 import com.google.protobuf.Value;
50 import com.google.protobuf.util.JsonFormat.TypeRegistry;
51 import com.google.protobuf.util.JsonTestProto.TestAllTypes;
52 import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
53 import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
54 import com.google.protobuf.util.JsonTestProto.TestAny;
55 import com.google.protobuf.util.JsonTestProto.TestCustomJsonName;
56 import com.google.protobuf.util.JsonTestProto.TestDuration;
57 import com.google.protobuf.util.JsonTestProto.TestFieldMask;
58 import com.google.protobuf.util.JsonTestProto.TestMap;
59 import com.google.protobuf.util.JsonTestProto.TestOneof;
60 import com.google.protobuf.util.JsonTestProto.TestStruct;
61 import com.google.protobuf.util.JsonTestProto.TestTimestamp;
62 import com.google.protobuf.util.JsonTestProto.TestWrappers;
63 
64 import junit.framework.TestCase;
65 
66 import java.io.IOException;
67 import java.math.BigDecimal;
68 import java.math.BigInteger;
69 
70 public class JsonFormatTest extends TestCase {
setAllFields(TestAllTypes.Builder builder)71   private void setAllFields(TestAllTypes.Builder builder) {
72     builder.setOptionalInt32(1234);
73     builder.setOptionalInt64(1234567890123456789L);
74     builder.setOptionalUint32(5678);
75     builder.setOptionalUint64(2345678901234567890L);
76     builder.setOptionalSint32(9012);
77     builder.setOptionalSint64(3456789012345678901L);
78     builder.setOptionalFixed32(3456);
79     builder.setOptionalFixed64(4567890123456789012L);
80     builder.setOptionalSfixed32(7890);
81     builder.setOptionalSfixed64(5678901234567890123L);
82     builder.setOptionalFloat(1.5f);
83     builder.setOptionalDouble(1.25);
84     builder.setOptionalBool(true);
85     builder.setOptionalString("Hello world!");
86     builder.setOptionalBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
87     builder.setOptionalNestedEnum(NestedEnum.BAR);
88     builder.getOptionalNestedMessageBuilder().setValue(100);
89 
90     builder.addRepeatedInt32(1234);
91     builder.addRepeatedInt64(1234567890123456789L);
92     builder.addRepeatedUint32(5678);
93     builder.addRepeatedUint64(2345678901234567890L);
94     builder.addRepeatedSint32(9012);
95     builder.addRepeatedSint64(3456789012345678901L);
96     builder.addRepeatedFixed32(3456);
97     builder.addRepeatedFixed64(4567890123456789012L);
98     builder.addRepeatedSfixed32(7890);
99     builder.addRepeatedSfixed64(5678901234567890123L);
100     builder.addRepeatedFloat(1.5f);
101     builder.addRepeatedDouble(1.25);
102     builder.addRepeatedBool(true);
103     builder.addRepeatedString("Hello world!");
104     builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
105     builder.addRepeatedNestedEnum(NestedEnum.BAR);
106     builder.addRepeatedNestedMessageBuilder().setValue(100);
107 
108     builder.addRepeatedInt32(234);
109     builder.addRepeatedInt64(234567890123456789L);
110     builder.addRepeatedUint32(678);
111     builder.addRepeatedUint64(345678901234567890L);
112     builder.addRepeatedSint32(012);
113     builder.addRepeatedSint64(456789012345678901L);
114     builder.addRepeatedFixed32(456);
115     builder.addRepeatedFixed64(567890123456789012L);
116     builder.addRepeatedSfixed32(890);
117     builder.addRepeatedSfixed64(678901234567890123L);
118     builder.addRepeatedFloat(11.5f);
119     builder.addRepeatedDouble(11.25);
120     builder.addRepeatedBool(true);
121     builder.addRepeatedString("ello world!");
122     builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {1, 2}));
123     builder.addRepeatedNestedEnum(NestedEnum.BAZ);
124     builder.addRepeatedNestedMessageBuilder().setValue(200);
125   }
126 
assertRoundTripEquals(Message message)127   private void assertRoundTripEquals(Message message) throws Exception {
128     assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
129   }
130 
assertRoundTripEquals(Message message, TypeRegistry registry)131   private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
132     JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
133     JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
134     Message.Builder builder = message.newBuilderForType();
135     parser.merge(printer.print(message), builder);
136     Message parsedMessage = builder.build();
137     assertEquals(message.toString(), parsedMessage.toString());
138   }
139 
toJsonString(Message message)140   private String toJsonString(Message message) throws IOException {
141     return JsonFormat.printer().print(message);
142   }
toCompactJsonString(Message message)143   private String toCompactJsonString(Message message) throws IOException {
144     return JsonFormat.printer().omittingInsignificantWhitespace().print(message);
145   }
146 
mergeFromJson(String json, Message.Builder builder)147   private void mergeFromJson(String json, Message.Builder builder) throws IOException {
148     JsonFormat.parser().merge(json, builder);
149   }
150 
testAllFields()151   public void testAllFields() throws Exception {
152     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
153     setAllFields(builder);
154     TestAllTypes message = builder.build();
155 
156     assertEquals(
157         "{\n"
158             + "  \"optionalInt32\": 1234,\n"
159             + "  \"optionalInt64\": \"1234567890123456789\",\n"
160             + "  \"optionalUint32\": 5678,\n"
161             + "  \"optionalUint64\": \"2345678901234567890\",\n"
162             + "  \"optionalSint32\": 9012,\n"
163             + "  \"optionalSint64\": \"3456789012345678901\",\n"
164             + "  \"optionalFixed32\": 3456,\n"
165             + "  \"optionalFixed64\": \"4567890123456789012\",\n"
166             + "  \"optionalSfixed32\": 7890,\n"
167             + "  \"optionalSfixed64\": \"5678901234567890123\",\n"
168             + "  \"optionalFloat\": 1.5,\n"
169             + "  \"optionalDouble\": 1.25,\n"
170             + "  \"optionalBool\": true,\n"
171             + "  \"optionalString\": \"Hello world!\",\n"
172             + "  \"optionalBytes\": \"AAEC\",\n"
173             + "  \"optionalNestedMessage\": {\n"
174             + "    \"value\": 100\n"
175             + "  },\n"
176             + "  \"optionalNestedEnum\": \"BAR\",\n"
177             + "  \"repeatedInt32\": [1234, 234],\n"
178             + "  \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
179             + "  \"repeatedUint32\": [5678, 678],\n"
180             + "  \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
181             + "  \"repeatedSint32\": [9012, 10],\n"
182             + "  \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
183             + "  \"repeatedFixed32\": [3456, 456],\n"
184             + "  \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
185             + "  \"repeatedSfixed32\": [7890, 890],\n"
186             + "  \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
187             + "  \"repeatedFloat\": [1.5, 11.5],\n"
188             + "  \"repeatedDouble\": [1.25, 11.25],\n"
189             + "  \"repeatedBool\": [true, true],\n"
190             + "  \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
191             + "  \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
192             + "  \"repeatedNestedMessage\": [{\n"
193             + "    \"value\": 100\n"
194             + "  }, {\n"
195             + "    \"value\": 200\n"
196             + "  }],\n"
197             + "  \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
198             + "}",
199         toJsonString(message));
200 
201     assertRoundTripEquals(message);
202   }
203 
testUnknownEnumValues()204   public void testUnknownEnumValues() throws Exception {
205     TestAllTypes message =
206         TestAllTypes.newBuilder()
207             .setOptionalNestedEnumValue(12345)
208             .addRepeatedNestedEnumValue(12345)
209             .addRepeatedNestedEnumValue(0)
210             .build();
211     assertEquals(
212         "{\n"
213             + "  \"optionalNestedEnum\": 12345,\n"
214             + "  \"repeatedNestedEnum\": [12345, \"FOO\"]\n"
215             + "}",
216         toJsonString(message));
217     assertRoundTripEquals(message);
218 
219     TestMap.Builder mapBuilder = TestMap.newBuilder();
220     mapBuilder.putInt32ToEnumMapValue(1, 0);
221     mapBuilder.getMutableInt32ToEnumMapValue().put(2, 12345);
222     TestMap mapMessage = mapBuilder.build();
223     assertEquals(
224         "{\n"
225             + "  \"int32ToEnumMap\": {\n"
226             + "    \"1\": \"FOO\",\n"
227             + "    \"2\": 12345\n"
228             + "  }\n"
229             + "}",
230         toJsonString(mapMessage));
231     assertRoundTripEquals(mapMessage);
232   }
233 
testSpecialFloatValues()234   public void testSpecialFloatValues() throws Exception {
235     TestAllTypes message =
236         TestAllTypes.newBuilder()
237             .addRepeatedFloat(Float.NaN)
238             .addRepeatedFloat(Float.POSITIVE_INFINITY)
239             .addRepeatedFloat(Float.NEGATIVE_INFINITY)
240             .addRepeatedDouble(Double.NaN)
241             .addRepeatedDouble(Double.POSITIVE_INFINITY)
242             .addRepeatedDouble(Double.NEGATIVE_INFINITY)
243             .build();
244     assertEquals(
245         "{\n"
246             + "  \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
247             + "  \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
248             + "}",
249         toJsonString(message));
250 
251     assertRoundTripEquals(message);
252   }
253 
testParserAcceptStringForNumbericField()254   public void testParserAcceptStringForNumbericField() throws Exception {
255     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
256     mergeFromJson(
257         "{\n"
258             + "  \"optionalInt32\": \"1234\",\n"
259             + "  \"optionalUint32\": \"5678\",\n"
260             + "  \"optionalSint32\": \"9012\",\n"
261             + "  \"optionalFixed32\": \"3456\",\n"
262             + "  \"optionalSfixed32\": \"7890\",\n"
263             + "  \"optionalFloat\": \"1.5\",\n"
264             + "  \"optionalDouble\": \"1.25\",\n"
265             + "  \"optionalBool\": \"true\"\n"
266             + "}",
267         builder);
268     TestAllTypes message = builder.build();
269     assertEquals(1234, message.getOptionalInt32());
270     assertEquals(5678, message.getOptionalUint32());
271     assertEquals(9012, message.getOptionalSint32());
272     assertEquals(3456, message.getOptionalFixed32());
273     assertEquals(7890, message.getOptionalSfixed32());
274     assertEquals(1.5f, message.getOptionalFloat());
275     assertEquals(1.25, message.getOptionalDouble());
276     assertEquals(true, message.getOptionalBool());
277   }
278 
testParserAcceptFloatingPointValueForIntegerField()279   public void testParserAcceptFloatingPointValueForIntegerField() throws Exception {
280     // Test that numeric values like "1.000", "1e5" will also be accepted.
281     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
282     mergeFromJson(
283         "{\n"
284             + "  \"repeatedInt32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
285             + "  \"repeatedUint32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
286             + "  \"repeatedInt64\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
287             + "  \"repeatedUint64\": [1.000, 1e5, \"1.000\", \"1e5\"]\n"
288             + "}",
289         builder);
290     int[] expectedValues = new int[] {1, 100000, 1, 100000};
291     assertEquals(4, builder.getRepeatedInt32Count());
292     assertEquals(4, builder.getRepeatedUint32Count());
293     assertEquals(4, builder.getRepeatedInt64Count());
294     assertEquals(4, builder.getRepeatedUint64Count());
295     for (int i = 0; i < 4; ++i) {
296       assertEquals(expectedValues[i], builder.getRepeatedInt32(i));
297       assertEquals(expectedValues[i], builder.getRepeatedUint32(i));
298       assertEquals(expectedValues[i], builder.getRepeatedInt64(i));
299       assertEquals(expectedValues[i], builder.getRepeatedUint64(i));
300     }
301 
302     // Non-integers will still be rejected.
303     assertRejects("optionalInt32", "1.5");
304     assertRejects("optionalUint32", "1.5");
305     assertRejects("optionalInt64", "1.5");
306     assertRejects("optionalUint64", "1.5");
307   }
308 
assertRejects(String name, String value)309   private void assertRejects(String name, String value) {
310     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
311     try {
312       // Numeric form is rejected.
313       mergeFromJson("{\"" + name + "\":" + value + "}", builder);
314       fail("Exception is expected.");
315     } catch (IOException e) {
316       // Expected.
317     }
318     try {
319       // String form is also rejected.
320       mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
321       fail("Exception is expected.");
322     } catch (IOException e) {
323       // Expected.
324     }
325   }
326 
assertAccepts(String name, String value)327   private void assertAccepts(String name, String value) throws IOException {
328     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
329     // Both numeric form and string form are accepted.
330     mergeFromJson("{\"" + name + "\":" + value + "}", builder);
331     builder.clear();
332     mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
333   }
334 
testParserRejectOutOfRangeNumericValues()335   public void testParserRejectOutOfRangeNumericValues() throws Exception {
336     assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
337     assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
338     assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
339     assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
340 
341     assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
342     assertRejects("optionalUint32", "123456789012345");
343     assertRejects("optionalUint32", "-1");
344 
345     BigInteger one = new BigInteger("1");
346     BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
347     BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
348     assertAccepts("optionalInt64", maxLong.toString());
349     assertAccepts("optionalInt64", minLong.toString());
350     assertRejects("optionalInt64", maxLong.add(one).toString());
351     assertRejects("optionalInt64", minLong.subtract(one).toString());
352 
353     assertAccepts("optionalUint64", maxLong.add(one).toString());
354     assertRejects("optionalUint64", "1234567890123456789012345");
355     assertRejects("optionalUint64", "-1");
356 
357     assertAccepts("optionalBool", "true");
358     assertRejects("optionalBool", "1");
359     assertRejects("optionalBool", "0");
360 
361     assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
362     assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
363     assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
364     assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
365 
366     BigDecimal moreThanOne = new BigDecimal("1.000001");
367     BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
368     BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
369     assertAccepts("optionalDouble", maxDouble.toString());
370     assertAccepts("optionalDouble", minDouble.toString());
371     assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
372     assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
373   }
374 
testParserAcceptNull()375   public void testParserAcceptNull() throws Exception {
376     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
377     mergeFromJson(
378         "{\n"
379             + "  \"optionalInt32\": null,\n"
380             + "  \"optionalInt64\": null,\n"
381             + "  \"optionalUint32\": null,\n"
382             + "  \"optionalUint64\": null,\n"
383             + "  \"optionalSint32\": null,\n"
384             + "  \"optionalSint64\": null,\n"
385             + "  \"optionalFixed32\": null,\n"
386             + "  \"optionalFixed64\": null,\n"
387             + "  \"optionalSfixed32\": null,\n"
388             + "  \"optionalSfixed64\": null,\n"
389             + "  \"optionalFloat\": null,\n"
390             + "  \"optionalDouble\": null,\n"
391             + "  \"optionalBool\": null,\n"
392             + "  \"optionalString\": null,\n"
393             + "  \"optionalBytes\": null,\n"
394             + "  \"optionalNestedMessage\": null,\n"
395             + "  \"optionalNestedEnum\": null,\n"
396             + "  \"repeatedInt32\": null,\n"
397             + "  \"repeatedInt64\": null,\n"
398             + "  \"repeatedUint32\": null,\n"
399             + "  \"repeatedUint64\": null,\n"
400             + "  \"repeatedSint32\": null,\n"
401             + "  \"repeatedSint64\": null,\n"
402             + "  \"repeatedFixed32\": null,\n"
403             + "  \"repeatedFixed64\": null,\n"
404             + "  \"repeatedSfixed32\": null,\n"
405             + "  \"repeatedSfixed64\": null,\n"
406             + "  \"repeatedFloat\": null,\n"
407             + "  \"repeatedDouble\": null,\n"
408             + "  \"repeatedBool\": null,\n"
409             + "  \"repeatedString\": null,\n"
410             + "  \"repeatedBytes\": null,\n"
411             + "  \"repeatedNestedMessage\": null,\n"
412             + "  \"repeatedNestedEnum\": null\n"
413             + "}",
414         builder);
415     TestAllTypes message = builder.build();
416     assertEquals(TestAllTypes.getDefaultInstance(), message);
417 
418     // Repeated field elements cannot be null.
419     try {
420       builder = TestAllTypes.newBuilder();
421       mergeFromJson("{\n" + "  \"repeatedInt32\": [null, null],\n" + "}", builder);
422       fail();
423     } catch (InvalidProtocolBufferException e) {
424       // Exception expected.
425     }
426 
427     try {
428       builder = TestAllTypes.newBuilder();
429       mergeFromJson("{\n" + "  \"repeatedNestedMessage\": [null, null],\n" + "}", builder);
430       fail();
431     } catch (InvalidProtocolBufferException e) {
432       // Exception expected.
433     }
434   }
435 
testNullInOneof()436   public void testNullInOneof() throws Exception {
437     TestOneof.Builder builder = TestOneof.newBuilder();
438     mergeFromJson("{\n" + "  \"oneofNullValue\": null \n" + "}", builder);
439     TestOneof message = builder.build();
440     assertEquals(TestOneof.OneofFieldCase.ONEOF_NULL_VALUE, message.getOneofFieldCase());
441     assertEquals(NullValue.NULL_VALUE, message.getOneofNullValue());
442   }
443 
testParserRejectDuplicatedFields()444   public void testParserRejectDuplicatedFields() throws Exception {
445     // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last
446     // one if multiple entries have the same name. This is not the desired behavior but it can
447     // only be fixed by using our own parser. Here we only test the cases where the names are
448     // different but still referring to the same field.
449 
450     // Duplicated optional fields.
451     try {
452       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
453       mergeFromJson(
454           "{\n"
455               + "  \"optionalNestedMessage\": {},\n"
456               + "  \"optional_nested_message\": {}\n"
457               + "}",
458           builder);
459       fail();
460     } catch (InvalidProtocolBufferException e) {
461       // Exception expected.
462     }
463 
464     // Duplicated repeated fields.
465     try {
466       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
467       mergeFromJson(
468           "{\n"
469               + "  \"repeatedNestedMessage\": [null, null],\n"
470               + "  \"repeated_nested_message\": [null, null]\n"
471               + "}",
472           builder);
473       fail();
474     } catch (InvalidProtocolBufferException e) {
475       // Exception expected.
476     }
477 
478     // Duplicated oneof fields.
479     try {
480       TestOneof.Builder builder = TestOneof.newBuilder();
481       mergeFromJson("{\n" + "  \"oneofInt32\": 1,\n" + "  \"oneof_int32\": 2\n" + "}", builder);
482       fail();
483     } catch (InvalidProtocolBufferException e) {
484       // Exception expected.
485     }
486   }
487 
testMapFields()488   public void testMapFields() throws Exception {
489     TestMap.Builder builder = TestMap.newBuilder();
490     builder.putInt32ToInt32Map(1, 10);
491     builder.putInt64ToInt32Map(1234567890123456789L, 10);
492     builder.putUint32ToInt32Map(2, 20);
493     builder.putUint64ToInt32Map(2234567890123456789L, 20);
494     builder.putSint32ToInt32Map(3, 30);
495     builder.putSint64ToInt32Map(3234567890123456789L, 30);
496     builder.putFixed32ToInt32Map(4, 40);
497     builder.putFixed64ToInt32Map(4234567890123456789L, 40);
498     builder.putSfixed32ToInt32Map(5, 50);
499     builder.putSfixed64ToInt32Map(5234567890123456789L, 50);
500     builder.putBoolToInt32Map(false, 6);
501     builder.putStringToInt32Map("Hello", 10);
502 
503     builder.putInt32ToInt64Map(1, 1234567890123456789L);
504     builder.putInt32ToUint32Map(2, 20);
505     builder.putInt32ToUint64Map(2, 2234567890123456789L);
506     builder.putInt32ToSint32Map(3, 30);
507     builder.putInt32ToSint64Map(3, 3234567890123456789L);
508     builder.putInt32ToFixed32Map(4, 40);
509     builder.putInt32ToFixed64Map(4, 4234567890123456789L);
510     builder.putInt32ToSfixed32Map(5, 50);
511     builder.putInt32ToSfixed64Map(5, 5234567890123456789L);
512     builder.putInt32ToFloatMap(6, 1.5f);
513     builder.putInt32ToDoubleMap(6, 1.25);
514     builder.putInt32ToBoolMap(7, false);
515     builder.putInt32ToStringMap(7, "World");
516     builder.putInt32ToBytesMap(8, ByteString.copyFrom(new byte[] {1, 2, 3}));
517     builder.putInt32ToMessageMap(8, NestedMessage.newBuilder().setValue(1234).build());
518     builder.putInt32ToEnumMap(9, NestedEnum.BAR);
519     TestMap message = builder.build();
520 
521     assertEquals(
522         "{\n"
523             + "  \"int32ToInt32Map\": {\n"
524             + "    \"1\": 10\n"
525             + "  },\n"
526             + "  \"int64ToInt32Map\": {\n"
527             + "    \"1234567890123456789\": 10\n"
528             + "  },\n"
529             + "  \"uint32ToInt32Map\": {\n"
530             + "    \"2\": 20\n"
531             + "  },\n"
532             + "  \"uint64ToInt32Map\": {\n"
533             + "    \"2234567890123456789\": 20\n"
534             + "  },\n"
535             + "  \"sint32ToInt32Map\": {\n"
536             + "    \"3\": 30\n"
537             + "  },\n"
538             + "  \"sint64ToInt32Map\": {\n"
539             + "    \"3234567890123456789\": 30\n"
540             + "  },\n"
541             + "  \"fixed32ToInt32Map\": {\n"
542             + "    \"4\": 40\n"
543             + "  },\n"
544             + "  \"fixed64ToInt32Map\": {\n"
545             + "    \"4234567890123456789\": 40\n"
546             + "  },\n"
547             + "  \"sfixed32ToInt32Map\": {\n"
548             + "    \"5\": 50\n"
549             + "  },\n"
550             + "  \"sfixed64ToInt32Map\": {\n"
551             + "    \"5234567890123456789\": 50\n"
552             + "  },\n"
553             + "  \"boolToInt32Map\": {\n"
554             + "    \"false\": 6\n"
555             + "  },\n"
556             + "  \"stringToInt32Map\": {\n"
557             + "    \"Hello\": 10\n"
558             + "  },\n"
559             + "  \"int32ToInt64Map\": {\n"
560             + "    \"1\": \"1234567890123456789\"\n"
561             + "  },\n"
562             + "  \"int32ToUint32Map\": {\n"
563             + "    \"2\": 20\n"
564             + "  },\n"
565             + "  \"int32ToUint64Map\": {\n"
566             + "    \"2\": \"2234567890123456789\"\n"
567             + "  },\n"
568             + "  \"int32ToSint32Map\": {\n"
569             + "    \"3\": 30\n"
570             + "  },\n"
571             + "  \"int32ToSint64Map\": {\n"
572             + "    \"3\": \"3234567890123456789\"\n"
573             + "  },\n"
574             + "  \"int32ToFixed32Map\": {\n"
575             + "    \"4\": 40\n"
576             + "  },\n"
577             + "  \"int32ToFixed64Map\": {\n"
578             + "    \"4\": \"4234567890123456789\"\n"
579             + "  },\n"
580             + "  \"int32ToSfixed32Map\": {\n"
581             + "    \"5\": 50\n"
582             + "  },\n"
583             + "  \"int32ToSfixed64Map\": {\n"
584             + "    \"5\": \"5234567890123456789\"\n"
585             + "  },\n"
586             + "  \"int32ToFloatMap\": {\n"
587             + "    \"6\": 1.5\n"
588             + "  },\n"
589             + "  \"int32ToDoubleMap\": {\n"
590             + "    \"6\": 1.25\n"
591             + "  },\n"
592             + "  \"int32ToBoolMap\": {\n"
593             + "    \"7\": false\n"
594             + "  },\n"
595             + "  \"int32ToStringMap\": {\n"
596             + "    \"7\": \"World\"\n"
597             + "  },\n"
598             + "  \"int32ToBytesMap\": {\n"
599             + "    \"8\": \"AQID\"\n"
600             + "  },\n"
601             + "  \"int32ToMessageMap\": {\n"
602             + "    \"8\": {\n"
603             + "      \"value\": 1234\n"
604             + "    }\n"
605             + "  },\n"
606             + "  \"int32ToEnumMap\": {\n"
607             + "    \"9\": \"BAR\"\n"
608             + "  }\n"
609             + "}",
610         toJsonString(message));
611     assertRoundTripEquals(message);
612 
613     // Test multiple entries.
614     builder = TestMap.newBuilder();
615     builder.putInt32ToInt32Map(1, 2);
616     builder.putInt32ToInt32Map(3, 4);
617     message = builder.build();
618 
619     assertEquals(
620         "{\n" + "  \"int32ToInt32Map\": {\n" + "    \"1\": 2,\n" + "    \"3\": 4\n" + "  }\n" + "}",
621         toJsonString(message));
622     assertRoundTripEquals(message);
623   }
624 
testMapNullValueIsRejected()625   public void testMapNullValueIsRejected() throws Exception {
626     try {
627       TestMap.Builder builder = TestMap.newBuilder();
628       mergeFromJson(
629           "{\n"
630               + "  \"int32ToInt32Map\": {null: 1},\n"
631               + "  \"int32ToMessageMap\": {null: 2}\n"
632               + "}",
633           builder);
634       fail();
635     } catch (InvalidProtocolBufferException e) {
636       // Exception expected.
637     }
638 
639     try {
640       TestMap.Builder builder = TestMap.newBuilder();
641       mergeFromJson(
642           "{\n"
643               + "  \"int32ToInt32Map\": {\"1\": null},\n"
644               + "  \"int32ToMessageMap\": {\"2\": null}\n"
645               + "}",
646           builder);
647       fail();
648     } catch (InvalidProtocolBufferException e) {
649       // Exception expected.
650     }
651   }
652 
testParserAcceptNonQuotedObjectKey()653   public void testParserAcceptNonQuotedObjectKey() throws Exception {
654     TestMap.Builder builder = TestMap.newBuilder();
655     mergeFromJson(
656         "{\n" + "  int32ToInt32Map: {1: 2},\n" + "  stringToInt32Map: {hello: 3}\n" + "}", builder);
657     TestMap message = builder.build();
658     assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
659     assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
660   }
661 
testWrappers()662   public void testWrappers() throws Exception {
663     TestWrappers.Builder builder = TestWrappers.newBuilder();
664     builder.getBoolValueBuilder().setValue(false);
665     builder.getInt32ValueBuilder().setValue(0);
666     builder.getInt64ValueBuilder().setValue(0);
667     builder.getUint32ValueBuilder().setValue(0);
668     builder.getUint64ValueBuilder().setValue(0);
669     builder.getFloatValueBuilder().setValue(0.0f);
670     builder.getDoubleValueBuilder().setValue(0.0);
671     builder.getStringValueBuilder().setValue("");
672     builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
673     TestWrappers message = builder.build();
674 
675     assertEquals(
676         "{\n"
677             + "  \"int32Value\": 0,\n"
678             + "  \"uint32Value\": 0,\n"
679             + "  \"int64Value\": \"0\",\n"
680             + "  \"uint64Value\": \"0\",\n"
681             + "  \"floatValue\": 0.0,\n"
682             + "  \"doubleValue\": 0.0,\n"
683             + "  \"boolValue\": false,\n"
684             + "  \"stringValue\": \"\",\n"
685             + "  \"bytesValue\": \"\"\n"
686             + "}",
687         toJsonString(message));
688     assertRoundTripEquals(message);
689 
690     builder = TestWrappers.newBuilder();
691     builder.getBoolValueBuilder().setValue(true);
692     builder.getInt32ValueBuilder().setValue(1);
693     builder.getInt64ValueBuilder().setValue(2);
694     builder.getUint32ValueBuilder().setValue(3);
695     builder.getUint64ValueBuilder().setValue(4);
696     builder.getFloatValueBuilder().setValue(5.0f);
697     builder.getDoubleValueBuilder().setValue(6.0);
698     builder.getStringValueBuilder().setValue("7");
699     builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[] {8}));
700     message = builder.build();
701 
702     assertEquals(
703         "{\n"
704             + "  \"int32Value\": 1,\n"
705             + "  \"uint32Value\": 3,\n"
706             + "  \"int64Value\": \"2\",\n"
707             + "  \"uint64Value\": \"4\",\n"
708             + "  \"floatValue\": 5.0,\n"
709             + "  \"doubleValue\": 6.0,\n"
710             + "  \"boolValue\": true,\n"
711             + "  \"stringValue\": \"7\",\n"
712             + "  \"bytesValue\": \"CA==\"\n"
713             + "}",
714         toJsonString(message));
715     assertRoundTripEquals(message);
716   }
717 
testTimestamp()718   public void testTimestamp() throws Exception {
719     TestTimestamp message =
720         TestTimestamp.newBuilder()
721             .setTimestampValue(Timestamps.parse("1970-01-01T00:00:00Z"))
722             .build();
723 
724     assertEquals(
725         "{\n" + "  \"timestampValue\": \"1970-01-01T00:00:00Z\"\n" + "}", toJsonString(message));
726     assertRoundTripEquals(message);
727   }
728 
testDuration()729   public void testDuration() throws Exception {
730     TestDuration message =
731         TestDuration.newBuilder().setDurationValue(Durations.parse("12345s")).build();
732 
733     assertEquals("{\n" + "  \"durationValue\": \"12345s\"\n" + "}", toJsonString(message));
734     assertRoundTripEquals(message);
735   }
736 
testFieldMask()737   public void testFieldMask() throws Exception {
738     TestFieldMask message =
739         TestFieldMask.newBuilder()
740             .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz,foo_bar.baz"))
741             .build();
742 
743     assertEquals(
744         "{\n" + "  \"fieldMaskValue\": \"foo.bar,baz,fooBar.baz\"\n" + "}", toJsonString(message));
745     assertRoundTripEquals(message);
746   }
747 
testStruct()748   public void testStruct() throws Exception {
749     // Build a struct with all possible values.
750     TestStruct.Builder builder = TestStruct.newBuilder();
751     Struct.Builder structBuilder = builder.getStructValueBuilder();
752     structBuilder.putFields("null_value", Value.newBuilder().setNullValueValue(0).build());
753     structBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1.25).build());
754     structBuilder.putFields("string_value", Value.newBuilder().setStringValue("hello").build());
755     Struct.Builder subStructBuilder = Struct.newBuilder();
756     subStructBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1234).build());
757     structBuilder.putFields(
758         "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
759     ListValue.Builder listBuilder = ListValue.newBuilder();
760     listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
761     listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
762     structBuilder.putFields(
763         "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
764     TestStruct message = builder.build();
765 
766     assertEquals(
767         "{\n"
768             + "  \"structValue\": {\n"
769             + "    \"null_value\": null,\n"
770             + "    \"number_value\": 1.25,\n"
771             + "    \"string_value\": \"hello\",\n"
772             + "    \"struct_value\": {\n"
773             + "      \"number_value\": 1234.0\n"
774             + "    },\n"
775             + "    \"list_value\": [1.125, null]\n"
776             + "  }\n"
777             + "}",
778         toJsonString(message));
779     assertRoundTripEquals(message);
780 
781     builder = TestStruct.newBuilder();
782     builder.setValue(Value.newBuilder().setNullValueValue(0).build());
783     message = builder.build();
784     assertEquals("{\n" + "  \"value\": null\n" + "}", toJsonString(message));
785     assertRoundTripEquals(message);
786 
787     builder = TestStruct.newBuilder();
788     listBuilder = builder.getListValueBuilder();
789     listBuilder.addValues(Value.newBuilder().setNumberValue(31831.125).build());
790     listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
791     message = builder.build();
792     assertEquals("{\n" + "  \"listValue\": [31831.125, null]\n" + "}", toJsonString(message));
793     assertRoundTripEquals(message);
794   }
795 
testAnyFields()796   public void testAnyFields() throws Exception {
797     TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
798     TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
799 
800     // A TypeRegistry must be provided in order to convert Any types.
801     try {
802       toJsonString(message);
803       fail("Exception is expected.");
804     } catch (IOException e) {
805       // Expected.
806     }
807 
808     JsonFormat.TypeRegistry registry =
809         JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
810     JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
811 
812     assertEquals(
813         "{\n"
814             + "  \"anyValue\": {\n"
815             + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
816             + "    \"optionalInt32\": 1234\n"
817             + "  }\n"
818             + "}",
819         printer.print(message));
820     assertRoundTripEquals(message, registry);
821 
822     // Well-known types have a special formatting when embedded in Any.
823     //
824     // 1. Any in Any.
825     Any anyMessage = Any.pack(Any.pack(content));
826     assertEquals(
827         "{\n"
828             + "  \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
829             + "  \"value\": {\n"
830             + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
831             + "    \"optionalInt32\": 1234\n"
832             + "  }\n"
833             + "}",
834         printer.print(anyMessage));
835     assertRoundTripEquals(anyMessage, registry);
836 
837     // 2. Wrappers in Any.
838     anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
839     assertEquals(
840         "{\n"
841             + "  \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
842             + "  \"value\": 12345\n"
843             + "}",
844         printer.print(anyMessage));
845     assertRoundTripEquals(anyMessage, registry);
846     anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
847     assertEquals(
848         "{\n"
849             + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
850             + "  \"value\": 12345\n"
851             + "}",
852         printer.print(anyMessage));
853     assertRoundTripEquals(anyMessage, registry);
854     anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
855     assertEquals(
856         "{\n"
857             + "  \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
858             + "  \"value\": \"12345\"\n"
859             + "}",
860         printer.print(anyMessage));
861     assertRoundTripEquals(anyMessage, registry);
862     anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
863     assertEquals(
864         "{\n"
865             + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
866             + "  \"value\": \"12345\"\n"
867             + "}",
868         printer.print(anyMessage));
869     assertRoundTripEquals(anyMessage, registry);
870     anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
871     assertEquals(
872         "{\n"
873             + "  \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
874             + "  \"value\": 12345.0\n"
875             + "}",
876         printer.print(anyMessage));
877     assertRoundTripEquals(anyMessage, registry);
878     anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
879     assertEquals(
880         "{\n"
881             + "  \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
882             + "  \"value\": 12345.0\n"
883             + "}",
884         printer.print(anyMessage));
885     assertRoundTripEquals(anyMessage, registry);
886     anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
887     assertEquals(
888         "{\n"
889             + "  \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
890             + "  \"value\": true\n"
891             + "}",
892         printer.print(anyMessage));
893     assertRoundTripEquals(anyMessage, registry);
894     anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
895     assertEquals(
896         "{\n"
897             + "  \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
898             + "  \"value\": \"Hello\"\n"
899             + "}",
900         printer.print(anyMessage));
901     assertRoundTripEquals(anyMessage, registry);
902     anyMessage =
903         Any.pack(BytesValue.newBuilder().setValue(ByteString.copyFrom(new byte[] {1, 2})).build());
904     assertEquals(
905         "{\n"
906             + "  \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
907             + "  \"value\": \"AQI=\"\n"
908             + "}",
909         printer.print(anyMessage));
910     assertRoundTripEquals(anyMessage, registry);
911 
912     // 3. Timestamp in Any.
913     anyMessage = Any.pack(Timestamps.parse("1969-12-31T23:59:59Z"));
914     assertEquals(
915         "{\n"
916             + "  \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
917             + "  \"value\": \"1969-12-31T23:59:59Z\"\n"
918             + "}",
919         printer.print(anyMessage));
920     assertRoundTripEquals(anyMessage, registry);
921 
922     // 4. Duration in Any
923     anyMessage = Any.pack(Durations.parse("12345.10s"));
924     assertEquals(
925         "{\n"
926             + "  \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
927             + "  \"value\": \"12345.100s\"\n"
928             + "}",
929         printer.print(anyMessage));
930     assertRoundTripEquals(anyMessage, registry);
931 
932     // 5. FieldMask in Any
933     anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
934     assertEquals(
935         "{\n"
936             + "  \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
937             + "  \"value\": \"foo.bar,baz\"\n"
938             + "}",
939         printer.print(anyMessage));
940     assertRoundTripEquals(anyMessage, registry);
941 
942     // 6. Struct in Any
943     Struct.Builder structBuilder = Struct.newBuilder();
944     structBuilder.putFields("number", Value.newBuilder().setNumberValue(1.125).build());
945     anyMessage = Any.pack(structBuilder.build());
946     assertEquals(
947         "{\n"
948             + "  \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
949             + "  \"value\": {\n"
950             + "    \"number\": 1.125\n"
951             + "  }\n"
952             + "}",
953         printer.print(anyMessage));
954     assertRoundTripEquals(anyMessage, registry);
955     Value.Builder valueBuilder = Value.newBuilder();
956     valueBuilder.setNumberValue(1);
957     anyMessage = Any.pack(valueBuilder.build());
958     assertEquals(
959         "{\n"
960             + "  \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
961             + "  \"value\": 1.0\n"
962             + "}",
963         printer.print(anyMessage));
964     assertRoundTripEquals(anyMessage, registry);
965   }
966 
testParserMissingTypeUrl()967   public void testParserMissingTypeUrl() throws Exception {
968     try {
969       Any.Builder builder = Any.newBuilder();
970       mergeFromJson("{\n" + "  \"optionalInt32\": 1234\n" + "}", builder);
971       fail("Exception is expected.");
972     } catch (IOException e) {
973       // Expected.
974     }
975   }
976 
testParserUnexpectedTypeUrl()977   public void testParserUnexpectedTypeUrl() throws Exception {
978     try {
979       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
980       mergeFromJson(
981           "{\n"
982               + "  \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
983               + "  \"optionalInt32\": 12345\n"
984               + "}",
985           builder);
986       fail("Exception is expected.");
987     } catch (IOException e) {
988       // Expected.
989     }
990   }
991 
testParserRejectTrailingComma()992   public void testParserRejectTrailingComma() throws Exception {
993     try {
994       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
995       mergeFromJson("{\n" + "  \"optionalInt32\": 12345,\n" + "}", builder);
996       fail("Exception is expected.");
997     } catch (IOException e) {
998       // Expected.
999     }
1000 
1001     // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
1002     // the JsonReader to non-lenient mode. If we want to enforce strict JSON
1003     // compliance, we might want to switch to a different JSON parser or
1004     // implement one by ourselves.
1005     // try {
1006     //   TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1007     //   JsonFormat.merge(
1008     //       "{\n"
1009     //       + "  \"repeatedInt32\": [12345,]\n"
1010     //       + "}", builder);
1011     //   fail("Exception is expected.");
1012     // } catch (IOException e) {
1013     //   // Expected.
1014     // }
1015   }
1016 
testParserRejectInvalidBase64()1017   public void testParserRejectInvalidBase64() throws Exception {
1018     assertRejects("optionalBytes", "!@#$");
1019     // We use standard BASE64 with paddings.
1020     assertRejects("optionalBytes", "AQI");
1021   }
1022 
testParserRejectInvalidEnumValue()1023   public void testParserRejectInvalidEnumValue() throws Exception {
1024     try {
1025       TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1026       mergeFromJson("{\n" + "  \"optionalNestedEnum\": \"XXX\"\n" + "}", builder);
1027       fail("Exception is expected.");
1028     } catch (InvalidProtocolBufferException e) {
1029       // Expected.
1030     }
1031   }
1032 
testCustomJsonName()1033   public void testCustomJsonName() throws Exception {
1034     TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
1035     assertEquals("{\n" + "  \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
1036     assertRoundTripEquals(message);
1037   }
1038 
testDefaultGsonDoesNotHtmlEscape()1039   public void testDefaultGsonDoesNotHtmlEscape() throws Exception {
1040     TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("=").build();
1041     assertEquals(
1042         "{\n" + "  \"optionalString\": \"=\"" + "\n}", JsonFormat.printer().print(message));
1043   }
1044 
testIncludingDefaultValueFields()1045   public void testIncludingDefaultValueFields() throws Exception {
1046     TestAllTypes message = TestAllTypes.getDefaultInstance();
1047     assertEquals("{\n}", JsonFormat.printer().print(message));
1048     assertEquals(
1049         "{\n"
1050             + "  \"optionalInt32\": 0,\n"
1051             + "  \"optionalInt64\": \"0\",\n"
1052             + "  \"optionalUint32\": 0,\n"
1053             + "  \"optionalUint64\": \"0\",\n"
1054             + "  \"optionalSint32\": 0,\n"
1055             + "  \"optionalSint64\": \"0\",\n"
1056             + "  \"optionalFixed32\": 0,\n"
1057             + "  \"optionalFixed64\": \"0\",\n"
1058             + "  \"optionalSfixed32\": 0,\n"
1059             + "  \"optionalSfixed64\": \"0\",\n"
1060             + "  \"optionalFloat\": 0.0,\n"
1061             + "  \"optionalDouble\": 0.0,\n"
1062             + "  \"optionalBool\": false,\n"
1063             + "  \"optionalString\": \"\",\n"
1064             + "  \"optionalBytes\": \"\",\n"
1065             + "  \"optionalNestedEnum\": \"FOO\",\n"
1066             + "  \"repeatedInt32\": [],\n"
1067             + "  \"repeatedInt64\": [],\n"
1068             + "  \"repeatedUint32\": [],\n"
1069             + "  \"repeatedUint64\": [],\n"
1070             + "  \"repeatedSint32\": [],\n"
1071             + "  \"repeatedSint64\": [],\n"
1072             + "  \"repeatedFixed32\": [],\n"
1073             + "  \"repeatedFixed64\": [],\n"
1074             + "  \"repeatedSfixed32\": [],\n"
1075             + "  \"repeatedSfixed64\": [],\n"
1076             + "  \"repeatedFloat\": [],\n"
1077             + "  \"repeatedDouble\": [],\n"
1078             + "  \"repeatedBool\": [],\n"
1079             + "  \"repeatedString\": [],\n"
1080             + "  \"repeatedBytes\": [],\n"
1081             + "  \"repeatedNestedMessage\": [],\n"
1082             + "  \"repeatedNestedEnum\": []\n"
1083             + "}",
1084         JsonFormat.printer().includingDefaultValueFields().print(message));
1085 
1086     TestMap mapMessage = TestMap.getDefaultInstance();
1087     assertEquals("{\n}", JsonFormat.printer().print(mapMessage));
1088     assertEquals(
1089         "{\n"
1090             + "  \"int32ToInt32Map\": {\n"
1091             + "  },\n"
1092             + "  \"int64ToInt32Map\": {\n"
1093             + "  },\n"
1094             + "  \"uint32ToInt32Map\": {\n"
1095             + "  },\n"
1096             + "  \"uint64ToInt32Map\": {\n"
1097             + "  },\n"
1098             + "  \"sint32ToInt32Map\": {\n"
1099             + "  },\n"
1100             + "  \"sint64ToInt32Map\": {\n"
1101             + "  },\n"
1102             + "  \"fixed32ToInt32Map\": {\n"
1103             + "  },\n"
1104             + "  \"fixed64ToInt32Map\": {\n"
1105             + "  },\n"
1106             + "  \"sfixed32ToInt32Map\": {\n"
1107             + "  },\n"
1108             + "  \"sfixed64ToInt32Map\": {\n"
1109             + "  },\n"
1110             + "  \"boolToInt32Map\": {\n"
1111             + "  },\n"
1112             + "  \"stringToInt32Map\": {\n"
1113             + "  },\n"
1114             + "  \"int32ToInt64Map\": {\n"
1115             + "  },\n"
1116             + "  \"int32ToUint32Map\": {\n"
1117             + "  },\n"
1118             + "  \"int32ToUint64Map\": {\n"
1119             + "  },\n"
1120             + "  \"int32ToSint32Map\": {\n"
1121             + "  },\n"
1122             + "  \"int32ToSint64Map\": {\n"
1123             + "  },\n"
1124             + "  \"int32ToFixed32Map\": {\n"
1125             + "  },\n"
1126             + "  \"int32ToFixed64Map\": {\n"
1127             + "  },\n"
1128             + "  \"int32ToSfixed32Map\": {\n"
1129             + "  },\n"
1130             + "  \"int32ToSfixed64Map\": {\n"
1131             + "  },\n"
1132             + "  \"int32ToFloatMap\": {\n"
1133             + "  },\n"
1134             + "  \"int32ToDoubleMap\": {\n"
1135             + "  },\n"
1136             + "  \"int32ToBoolMap\": {\n"
1137             + "  },\n"
1138             + "  \"int32ToStringMap\": {\n"
1139             + "  },\n"
1140             + "  \"int32ToBytesMap\": {\n"
1141             + "  },\n"
1142             + "  \"int32ToMessageMap\": {\n"
1143             + "  },\n"
1144             + "  \"int32ToEnumMap\": {\n"
1145             + "  }\n"
1146             + "}",
1147         JsonFormat.printer().includingDefaultValueFields().print(mapMessage));
1148   }
1149 
testPreservingProtoFieldNames()1150   public void testPreservingProtoFieldNames() throws Exception {
1151     TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
1152     assertEquals("{\n" + "  \"optionalInt32\": 12345\n" + "}", JsonFormat.printer().print(message));
1153     assertEquals(
1154         "{\n" + "  \"optional_int32\": 12345\n" + "}",
1155         JsonFormat.printer().preservingProtoFieldNames().print(message));
1156 
1157     // The json_name field option is ignored when configured to use original proto field names.
1158     TestCustomJsonName messageWithCustomJsonName =
1159         TestCustomJsonName.newBuilder().setValue(12345).build();
1160     assertEquals(
1161         "{\n" + "  \"value\": 12345\n" + "}",
1162         JsonFormat.printer().preservingProtoFieldNames().print(messageWithCustomJsonName));
1163 
1164     // Parsers accept both original proto field names and lowerCamelCase names.
1165     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1166     JsonFormat.parser().merge("{\"optionalInt32\": 12345}", builder);
1167     assertEquals(12345, builder.getOptionalInt32());
1168     builder.clear();
1169     JsonFormat.parser().merge("{\"optional_int32\": 54321}", builder);
1170     assertEquals(54321, builder.getOptionalInt32());
1171   }
1172 
testOmittingInsignificantWhiteSpace()1173   public void testOmittingInsignificantWhiteSpace() throws Exception {
1174     TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
1175     assertEquals(
1176         "{" + "\"optionalInt32\":12345" + "}",
1177         JsonFormat.printer().omittingInsignificantWhitespace().print(message));
1178     TestAllTypes message1 = TestAllTypes.getDefaultInstance();
1179     assertEquals("{}", JsonFormat.printer().omittingInsignificantWhitespace().print(message1));
1180     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
1181     setAllFields(builder);
1182     TestAllTypes message2 = builder.build();
1183     assertEquals(
1184         "{"
1185             + "\"optionalInt32\":1234,"
1186             + "\"optionalInt64\":\"1234567890123456789\","
1187             + "\"optionalUint32\":5678,"
1188             + "\"optionalUint64\":\"2345678901234567890\","
1189             + "\"optionalSint32\":9012,"
1190             + "\"optionalSint64\":\"3456789012345678901\","
1191             + "\"optionalFixed32\":3456,"
1192             + "\"optionalFixed64\":\"4567890123456789012\","
1193             + "\"optionalSfixed32\":7890,"
1194             + "\"optionalSfixed64\":\"5678901234567890123\","
1195             + "\"optionalFloat\":1.5,"
1196             + "\"optionalDouble\":1.25,"
1197             + "\"optionalBool\":true,"
1198             + "\"optionalString\":\"Hello world!\","
1199             + "\"optionalBytes\":\"AAEC\","
1200             + "\"optionalNestedMessage\":{"
1201             + "\"value\":100"
1202             + "},"
1203             + "\"optionalNestedEnum\":\"BAR\","
1204             + "\"repeatedInt32\":[1234,234],"
1205             + "\"repeatedInt64\":[\"1234567890123456789\",\"234567890123456789\"],"
1206             + "\"repeatedUint32\":[5678,678],"
1207             + "\"repeatedUint64\":[\"2345678901234567890\",\"345678901234567890\"],"
1208             + "\"repeatedSint32\":[9012,10],"
1209             + "\"repeatedSint64\":[\"3456789012345678901\",\"456789012345678901\"],"
1210             + "\"repeatedFixed32\":[3456,456],"
1211             + "\"repeatedFixed64\":[\"4567890123456789012\",\"567890123456789012\"],"
1212             + "\"repeatedSfixed32\":[7890,890],"
1213             + "\"repeatedSfixed64\":[\"5678901234567890123\",\"678901234567890123\"],"
1214             + "\"repeatedFloat\":[1.5,11.5],"
1215             + "\"repeatedDouble\":[1.25,11.25],"
1216             + "\"repeatedBool\":[true,true],"
1217             + "\"repeatedString\":[\"Hello world!\",\"ello world!\"],"
1218             + "\"repeatedBytes\":[\"AAEC\",\"AQI=\"],"
1219             + "\"repeatedNestedMessage\":[{"
1220             + "\"value\":100"
1221             + "},{"
1222             + "\"value\":200"
1223             + "}],"
1224             + "\"repeatedNestedEnum\":[\"BAR\",\"BAZ\"]"
1225             + "}",
1226         toCompactJsonString(message2));
1227   }
1228 
1229   // Regression test for b/29892357
testEmptyWrapperTypesInAny()1230   public void testEmptyWrapperTypesInAny() throws Exception {
1231     JsonFormat.TypeRegistry registry =
1232         JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
1233     JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
1234 
1235     Any.Builder builder = Any.newBuilder();
1236     parser.merge(
1237         "{\n"
1238             + "  \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
1239             + "  \"value\": false\n"
1240             + "}\n",
1241         builder);
1242     Any any = builder.build();
1243     assertEquals(0, any.getValue().size());
1244   }
1245 }
1246