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