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