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