001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.json; 014 015import static org.apache.juneau.collections.JsonMap.*; 016 017import java.lang.annotation.*; 018import java.lang.reflect.*; 019import java.nio.charset.*; 020import java.util.*; 021import java.util.concurrent.*; 022 023import org.apache.juneau.*; 024import org.apache.juneau.collections.*; 025import org.apache.juneau.internal.*; 026import org.apache.juneau.serializer.*; 027import org.apache.juneau.utils.*; 028 029/** 030 * Serializes POJO models to JSON. 031 * 032 * <h5 class='topic'>Media types</h5> 033 * <p> 034 * Handles <c>Accept</c> types: <bc>application/json, text/json</bc> 035 * <p> 036 * Produces <c>Content-Type</c> types: <bc>application/json</bc> 037 * 038 * <h5 class='topic'>Description</h5> 039 * <p> 040 * The conversion is as follows... 041 * <ul class='spaced-list'> 042 * <li> 043 * Maps (e.g. {@link HashMap HashMaps}, {@link TreeMap TreeMaps}) are converted to JSON objects. 044 * <li> 045 * Collections (e.g. {@link HashSet HashSets}, {@link LinkedList LinkedLists}) and Java arrays are converted to 046 * JSON arrays. 047 * <li> 048 * {@link String Strings} are converted to JSON strings. 049 * <li> 050 * {@link Number Numbers} (e.g. {@link Integer}, {@link Long}, {@link Double}) are converted to JSON numbers. 051 * <li> 052 * {@link Boolean Booleans} are converted to JSON booleans. 053 * <li> 054 * {@code nulls} are converted to JSON nulls. 055 * <li> 056 * {@code arrays} are converted to JSON arrays. 057 * <li> 058 * {@code beans} are converted to JSON objects. 059 * </ul> 060 * 061 * <p> 062 * The types above are considered "JSON-primitive" object types. 063 * Any non-JSON-primitive object types are transformed into JSON-primitive object types through 064 * {@link org.apache.juneau.swap.ObjectSwap ObjectSwaps} associated through the 065 * {@link org.apache.juneau.BeanContext.Builder#swaps(Class...)} method. 066 * Several default transforms are provided for transforming Dates, Enums, Iterators, etc... 067 * 068 * <p> 069 * This serializer provides several serialization options. 070 * Typically, one of the predefined DEFAULT serializers will be sufficient. 071 * However, custom serializers can be constructed to fine-tune behavior. 072 * 073 * <h5 class='topic'>Behavior-specific subclasses</h5> 074 * <p> 075 * The following direct subclasses are provided for convenience: 076 * <ul class='spaced-list'> 077 * <li> 078 * {@link Json5Serializer} - Default serializer, single quotes, simple mode. 079 * <li> 080 * {@link Json5Serializer.Readable} - Default serializer, single quotes, simple mode, with whitespace. 081 * </ul> 082 * 083 * <h5 class='section'>Example:</h5> 084 * <p class='bjava'> 085 * <jc>// Use one of the default serializers to serialize a POJO</jc> 086 * String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>someObject</jv>); 087 * 088 * <jc>// Create a custom serializer for lax syntax using single quote characters</jc> 089 * JsonSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().simple().sq().build(); 090 * 091 * <jc>// Clone an existing serializer and modify it to use single-quotes</jc> 092 * <jv>serializer</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.copy().sq().build(); 093 * 094 * <jc>// Serialize a POJO to JSON</jc> 095 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>someObject</jv>); 096 * </p> 097 * 098 * <h5 class='section'>Notes:</h5><ul> 099 * <li class='note'>This class is thread safe and reusable. 100 * </ul> 101 * 102 * <h5 class='section'>See Also:</h5><ul> 103 * <li class='link'><a class="doclink" href="../../../../index.html#jm.JsonDetails">JSON Details</a> 104 105 * </ul> 106 */ 107public class JsonSerializer extends WriterSerializer implements JsonMetaProvider { 108 109 //------------------------------------------------------------------------------------------------------------------- 110 // Static 111 //------------------------------------------------------------------------------------------------------------------- 112 113 /** Default serializer, all default settings.*/ 114 public static final JsonSerializer DEFAULT = new JsonSerializer(create()); 115 116 /** Default serializer, all default settings.*/ 117 public static final JsonSerializer DEFAULT_READABLE = new Readable(create()); 118 119 /** 120 * Creates a new builder for this object. 121 * 122 * @return A new builder. 123 */ 124 public static Builder create() { 125 return new Builder(); 126 } 127 128 //------------------------------------------------------------------------------------------------------------------- 129 // Static subclasses 130 //------------------------------------------------------------------------------------------------------------------- 131 132 /** Default serializer, with whitespace. */ 133 public static class Readable extends JsonSerializer { 134 135 /** 136 * Constructor. 137 * 138 * @param builder The builder for this object. 139 */ 140 public Readable(Builder builder) { 141 super(builder.useWhitespace()); 142 } 143 } 144 145 /** 146 * Default serializer, single quotes, simple mode, with whitespace and recursion detection. 147 * Note that recursion detection introduces a small performance penalty. 148 */ 149 public static class ReadableSafe extends JsonSerializer { 150 151 /** 152 * Constructor. 153 * 154 * @param builder The builder for this object. 155 */ 156 public ReadableSafe(Builder builder) { 157 super(builder.simpleAttrs().useWhitespace().detectRecursions()); 158 } 159 } 160 161 //------------------------------------------------------------------------------------------------------------------- 162 // Builder 163 //------------------------------------------------------------------------------------------------------------------- 164 165 /** 166 * Builder class. 167 */ 168 @FluentSetters 169 public static class Builder extends WriterSerializer.Builder { 170 171 private static final Cache<HashKey,JsonSerializer> CACHE = Cache.of(HashKey.class, JsonSerializer.class).build(); 172 173 boolean addBeanTypesJson, escapeSolidus, simpleAttrs; 174 175 /** 176 * Constructor, default settings. 177 */ 178 protected Builder() { 179 produces("application/json"); 180 accept("application/json,text/json"); 181 addBeanTypesJson = env("JsonSerializer.addBeanTypes", false); 182 escapeSolidus = env("JsonSerializer.escapeSolidus", false); 183 simpleAttrs = env("JsonSerializer.simpleAttrs", false); 184 } 185 186 /** 187 * Copy constructor. 188 * 189 * @param copyFrom The bean to copy from. 190 */ 191 protected Builder(JsonSerializer copyFrom) { 192 super(copyFrom); 193 addBeanTypesJson = copyFrom.addBeanTypesJson; 194 escapeSolidus = copyFrom.escapeSolidus; 195 simpleAttrs = copyFrom.simpleAttrs; 196 } 197 198 /** 199 * Copy constructor. 200 * 201 * @param copyFrom The builder to copy from. 202 */ 203 protected Builder(Builder copyFrom) { 204 super(copyFrom); 205 addBeanTypesJson = copyFrom.addBeanTypesJson; 206 escapeSolidus = copyFrom.escapeSolidus; 207 simpleAttrs = copyFrom.simpleAttrs; 208 } 209 210 @Override /* Context.Builder */ 211 public Builder copy() { 212 return new Builder(this); 213 } 214 215 @Override /* Context.Builder */ 216 public JsonSerializer build() { 217 return cache(CACHE).build(JsonSerializer.class); 218 } 219 220 @Override /* Context.Builder */ 221 public HashKey hashKey() { 222 return HashKey.of( 223 super.hashKey(), 224 addBeanTypesJson, 225 escapeSolidus, 226 simpleAttrs 227 ); 228 } 229 230 //----------------------------------------------------------------------------------------------------------------- 231 // Properties 232 //----------------------------------------------------------------------------------------------------------------- 233 234 /** 235 * Add <js>"_type"</js> properties when needed. 236 * 237 * <p> 238 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred 239 * through reflection. 240 * 241 * <p> 242 * When present, this value overrides the {@link org.apache.juneau.serializer.Serializer.Builder#addBeanTypes()} setting and is 243 * provided to customize the behavior of specific serializers in a {@link SerializerSet}. 244 * 245 * @return This object. 246 */ 247 @FluentSetter 248 public Builder addBeanTypesJson() { 249 return addBeanTypesJson(true); 250 } 251 252 /** 253 * Same as {@link #addBeanTypesJson()} but allows you to explicitly specify the value. 254 * 255 * @param value The value for this setting. 256 * @return This object. 257 */ 258 @FluentSetter 259 public Builder addBeanTypesJson(boolean value) { 260 addBeanTypesJson = value; 261 return this; 262 } 263 264 /** 265 * Prefix solidus <js>'/'</js> characters with escapes. 266 * 267 * <p> 268 * If enabled, solidus (e.g. slash) characters should be escaped. 269 * 270 * <p> 271 * The JSON specification allows for either format. 272 * <br>However, if you're embedding JSON in an HTML script tag, this setting prevents confusion when trying to serialize 273 * <xt><\/script></xt>. 274 * 275 * <h5 class='section'>Example:</h5> 276 * <p class='bjava'> 277 * <jc>// Create a JSON serializer that escapes solidus characters.</jc> 278 * WriterSerializer <jv>serializer</jv> = JsonSerializer 279 * .<jsm>create</jsm>() 280 * .simple() 281 * .escapeSolidus() 282 * .build(); 283 * 284 * <jc>// Produces: "{foo:'<\/bar>'"</jc> 285 * String <jv>json</jv> = <jv>serializer</jv>.serialize(JsonMap.<jsm>of</jsm>(<js>"foo"</js>, <js>"</bar>"</js>); 286 * </p> 287 * 288 * @return This object. 289 */ 290 @FluentSetter 291 public Builder escapeSolidus() { 292 return escapeSolidus(true); 293 } 294 295 /** 296 * Same as {@link #escapeSolidus()} but allows you to explicitly specify the value. 297 * 298 * @param value The value for this setting. 299 * @return This object. 300 */ 301 @FluentSetter 302 public Builder escapeSolidus(boolean value) { 303 escapeSolidus = value; 304 return this; 305 } 306 307 /** 308 * Simple JSON attributes mode. 309 * 310 * <p> 311 * If enabled, JSON attribute names will only be quoted when necessary. 312 * <br>Otherwise, they are always quoted. 313 * 314 * <p> 315 * Attributes do not need to be quoted when they conform to the following: 316 * <ol class='spaced-list'> 317 * <li>They start with an ASCII character or <js>'_'</js>. 318 * <li>They contain only ASCII characters or numbers or <js>'_'</js>. 319 * <li>They are not one of the following reserved words: 320 * <p class='bcode'> 321 * arguments, break, case, catch, class, const, continue, debugger, default, 322 * delete, do, else, enum, eval, export, extends, false, finally, for, function, 323 * if, implements, import, in, instanceof, interface, let, new, null, package, 324 * private, protected, public, return, static, super, switch, this, throw, 325 * true, try, typeof, var, void, while, with, undefined, yield 326 * </p> 327 * </ol> 328 * 329 * <h5 class='section'>Example:</h5> 330 * <p class='bjava'> 331 * <jc>// Create a JSON serializer in normal mode.</jc> 332 * WriterSerializer <jv>serializer1</jv> = JsonSerializer 333 * .<jsm>create</jsm>() 334 * .build(); 335 * 336 * <jc>// Create a JSON serializer in simple mode.</jc> 337 * WriterSerializer <jv>serializer2</jv> = JsonSerializer 338 * .<jsm>create</jsm>() 339 * .simpleAttrs() 340 * .build(); 341 * 342 * JsonMap <jv>myMap</jv> = JsonMap.<jsm>of</jsm>( 343 * <js>"foo"</js>, <js>"x1"</js>, 344 * <js>"_bar"</js>, <js>"x2"</js>, 345 * <js>" baz "</js>, <js>"x3"</js>, 346 * <js>"123"</js>, <js>"x4"</js>, 347 * <js>"return"</js>, <js>"x5"</js>, 348 * <js>""</js>, <js>"x6"</js> 349 * ); 350 * 351 * <jc>// Produces:</jc> 352 * <jc>// {</jc> 353 * <jc>// "foo": "x1"</jc> 354 * <jc>// "_bar": "x2"</jc> 355 * <jc>// " baz ": "x3"</jc> 356 * <jc>// "123": "x4"</jc> 357 * <jc>// "return": "x5"</jc> 358 * <jc>// "": "x6"</jc> 359 * <jc>// }</jc> 360 * String <jv>json1</jv> = <jv>serializer1</jv>.serialize(<jv>myMap</jv>); 361 * 362 * <jc>// Produces:</jc> 363 * <jc>// {</jc> 364 * <jc>// foo: "x1"</jc> 365 * <jc>// _bar: "x2"</jc> 366 * <jc>// " baz ": "x3"</jc> 367 * <jc>// "123": "x4"</jc> 368 * <jc>// "return": "x5"</jc> 369 * <jc>// "": "x6"</jc> 370 * <jc>// }</jc> 371 * String <jv>json2</jv> = <jv>serializer2</jv>.serialize(<jv>myMap</jv>); 372 * </p> 373 * 374 * @return This object. 375 */ 376 @FluentSetter 377 public Builder simpleAttrs() { 378 return simpleAttrs(true); 379 } 380 381 /** 382 * Same as {@link #simpleAttrs()} but allows you to explicitly specify the value. 383 * 384 * @param value The value for this setting. 385 * @return This object. 386 */ 387 @FluentSetter 388 public Builder simpleAttrs(boolean value) { 389 simpleAttrs = value; 390 return this; 391 } 392 393 /** 394 * Simple JSON mode and single quote. 395 * 396 * <p> 397 * Shortcut for calling <c>simple().sq()</c>. 398 * 399 * <h5 class='section'>See Also:</h5><ul> 400 * <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#quoteChar(char)} 401 * </ul> 402 * 403 * @return This object. 404 */ 405 @FluentSetter 406 public Builder json5() { 407 return simpleAttrs().sq(); 408 } 409 410 // <FluentSetters> 411 412 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 413 public Builder annotations(Annotation...values) { 414 super.annotations(values); 415 return this; 416 } 417 418 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 419 public Builder apply(AnnotationWorkList work) { 420 super.apply(work); 421 return this; 422 } 423 424 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 425 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 426 super.applyAnnotations(fromClasses); 427 return this; 428 } 429 430 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 431 public Builder applyAnnotations(Method...fromMethods) { 432 super.applyAnnotations(fromMethods); 433 return this; 434 } 435 436 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 437 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 438 super.cache(value); 439 return this; 440 } 441 442 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 443 public Builder debug() { 444 super.debug(); 445 return this; 446 } 447 448 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 449 public Builder debug(boolean value) { 450 super.debug(value); 451 return this; 452 } 453 454 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 455 public Builder impl(Context value) { 456 super.impl(value); 457 return this; 458 } 459 460 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 461 public Builder type(Class<? extends org.apache.juneau.Context> value) { 462 super.type(value); 463 return this; 464 } 465 466 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 467 public Builder beanClassVisibility(Visibility value) { 468 super.beanClassVisibility(value); 469 return this; 470 } 471 472 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 473 public Builder beanConstructorVisibility(Visibility value) { 474 super.beanConstructorVisibility(value); 475 return this; 476 } 477 478 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 479 public Builder beanContext(BeanContext value) { 480 super.beanContext(value); 481 return this; 482 } 483 484 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 485 public Builder beanContext(BeanContext.Builder value) { 486 super.beanContext(value); 487 return this; 488 } 489 490 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 491 public Builder beanDictionary(java.lang.Class<?>...values) { 492 super.beanDictionary(values); 493 return this; 494 } 495 496 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 497 public Builder beanFieldVisibility(Visibility value) { 498 super.beanFieldVisibility(value); 499 return this; 500 } 501 502 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 503 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 504 super.beanInterceptor(on, value); 505 return this; 506 } 507 508 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 509 public Builder beanMapPutReturnsOldValue() { 510 super.beanMapPutReturnsOldValue(); 511 return this; 512 } 513 514 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 515 public Builder beanMethodVisibility(Visibility value) { 516 super.beanMethodVisibility(value); 517 return this; 518 } 519 520 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 521 public Builder beanProperties(Map<String,Object> values) { 522 super.beanProperties(values); 523 return this; 524 } 525 526 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 527 public Builder beanProperties(Class<?> beanClass, String properties) { 528 super.beanProperties(beanClass, properties); 529 return this; 530 } 531 532 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 533 public Builder beanProperties(String beanClassName, String properties) { 534 super.beanProperties(beanClassName, properties); 535 return this; 536 } 537 538 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 539 public Builder beanPropertiesExcludes(Map<String,Object> values) { 540 super.beanPropertiesExcludes(values); 541 return this; 542 } 543 544 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 545 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 546 super.beanPropertiesExcludes(beanClass, properties); 547 return this; 548 } 549 550 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 551 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 552 super.beanPropertiesExcludes(beanClassName, properties); 553 return this; 554 } 555 556 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 557 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 558 super.beanPropertiesReadOnly(values); 559 return this; 560 } 561 562 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 563 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 564 super.beanPropertiesReadOnly(beanClass, properties); 565 return this; 566 } 567 568 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 569 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 570 super.beanPropertiesReadOnly(beanClassName, properties); 571 return this; 572 } 573 574 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 575 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 576 super.beanPropertiesWriteOnly(values); 577 return this; 578 } 579 580 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 581 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 582 super.beanPropertiesWriteOnly(beanClass, properties); 583 return this; 584 } 585 586 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 587 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 588 super.beanPropertiesWriteOnly(beanClassName, properties); 589 return this; 590 } 591 592 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 593 public Builder beansRequireDefaultConstructor() { 594 super.beansRequireDefaultConstructor(); 595 return this; 596 } 597 598 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 599 public Builder beansRequireSerializable() { 600 super.beansRequireSerializable(); 601 return this; 602 } 603 604 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 605 public Builder beansRequireSettersForGetters() { 606 super.beansRequireSettersForGetters(); 607 return this; 608 } 609 610 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 611 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 612 super.dictionaryOn(on, values); 613 return this; 614 } 615 616 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 617 public Builder disableBeansRequireSomeProperties() { 618 super.disableBeansRequireSomeProperties(); 619 return this; 620 } 621 622 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 623 public Builder disableIgnoreMissingSetters() { 624 super.disableIgnoreMissingSetters(); 625 return this; 626 } 627 628 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 629 public Builder disableIgnoreTransientFields() { 630 super.disableIgnoreTransientFields(); 631 return this; 632 } 633 634 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 635 public Builder disableIgnoreUnknownNullBeanProperties() { 636 super.disableIgnoreUnknownNullBeanProperties(); 637 return this; 638 } 639 640 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 641 public Builder disableInterfaceProxies() { 642 super.disableInterfaceProxies(); 643 return this; 644 } 645 646 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 647 public <T> Builder example(Class<T> pojoClass, T o) { 648 super.example(pojoClass, o); 649 return this; 650 } 651 652 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 653 public <T> Builder example(Class<T> pojoClass, String json) { 654 super.example(pojoClass, json); 655 return this; 656 } 657 658 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 659 public Builder findFluentSetters() { 660 super.findFluentSetters(); 661 return this; 662 } 663 664 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 665 public Builder findFluentSetters(Class<?> on) { 666 super.findFluentSetters(on); 667 return this; 668 } 669 670 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 671 public Builder ignoreInvocationExceptionsOnGetters() { 672 super.ignoreInvocationExceptionsOnGetters(); 673 return this; 674 } 675 676 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 677 public Builder ignoreInvocationExceptionsOnSetters() { 678 super.ignoreInvocationExceptionsOnSetters(); 679 return this; 680 } 681 682 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 683 public Builder ignoreUnknownBeanProperties() { 684 super.ignoreUnknownBeanProperties(); 685 return this; 686 } 687 688 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 689 public Builder ignoreUnknownEnumValues() { 690 super.ignoreUnknownEnumValues(); 691 return this; 692 } 693 694 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 695 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 696 super.implClass(interfaceClass, implClass); 697 return this; 698 } 699 700 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 701 public Builder implClasses(Map<Class<?>,Class<?>> values) { 702 super.implClasses(values); 703 return this; 704 } 705 706 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 707 public Builder interfaceClass(Class<?> on, Class<?> value) { 708 super.interfaceClass(on, value); 709 return this; 710 } 711 712 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 713 public Builder interfaces(java.lang.Class<?>...value) { 714 super.interfaces(value); 715 return this; 716 } 717 718 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 719 public Builder locale(Locale value) { 720 super.locale(value); 721 return this; 722 } 723 724 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 725 public Builder mediaType(MediaType value) { 726 super.mediaType(value); 727 return this; 728 } 729 730 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 731 public Builder notBeanClasses(java.lang.Class<?>...values) { 732 super.notBeanClasses(values); 733 return this; 734 } 735 736 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 737 public Builder notBeanPackages(String...values) { 738 super.notBeanPackages(values); 739 return this; 740 } 741 742 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 743 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 744 super.propertyNamer(value); 745 return this; 746 } 747 748 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 749 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 750 super.propertyNamer(on, value); 751 return this; 752 } 753 754 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 755 public Builder sortProperties() { 756 super.sortProperties(); 757 return this; 758 } 759 760 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 761 public Builder sortProperties(java.lang.Class<?>...on) { 762 super.sortProperties(on); 763 return this; 764 } 765 766 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 767 public Builder stopClass(Class<?> on, Class<?> value) { 768 super.stopClass(on, value); 769 return this; 770 } 771 772 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 773 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 774 super.swap(normalClass, swappedClass, swapFunction); 775 return this; 776 } 777 778 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 779 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 780 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 781 return this; 782 } 783 784 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 785 public Builder swaps(java.lang.Class<?>...values) { 786 super.swaps(values); 787 return this; 788 } 789 790 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 791 public Builder timeZone(TimeZone value) { 792 super.timeZone(value); 793 return this; 794 } 795 796 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 797 public Builder typeName(Class<?> on, String value) { 798 super.typeName(on, value); 799 return this; 800 } 801 802 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 803 public Builder typePropertyName(String value) { 804 super.typePropertyName(value); 805 return this; 806 } 807 808 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 809 public Builder typePropertyName(Class<?> on, String value) { 810 super.typePropertyName(on, value); 811 return this; 812 } 813 814 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 815 public Builder useEnumNames() { 816 super.useEnumNames(); 817 return this; 818 } 819 820 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 821 public Builder useJavaBeanIntrospector() { 822 super.useJavaBeanIntrospector(); 823 return this; 824 } 825 826 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 827 public Builder detectRecursions() { 828 super.detectRecursions(); 829 return this; 830 } 831 832 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 833 public Builder detectRecursions(boolean value) { 834 super.detectRecursions(value); 835 return this; 836 } 837 838 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 839 public Builder ignoreRecursions() { 840 super.ignoreRecursions(); 841 return this; 842 } 843 844 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 845 public Builder ignoreRecursions(boolean value) { 846 super.ignoreRecursions(value); 847 return this; 848 } 849 850 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 851 public Builder initialDepth(int value) { 852 super.initialDepth(value); 853 return this; 854 } 855 856 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 857 public Builder maxDepth(int value) { 858 super.maxDepth(value); 859 return this; 860 } 861 862 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 863 public Builder accept(String value) { 864 super.accept(value); 865 return this; 866 } 867 868 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 869 public Builder addBeanTypes() { 870 super.addBeanTypes(); 871 return this; 872 } 873 874 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 875 public Builder addBeanTypes(boolean value) { 876 super.addBeanTypes(value); 877 return this; 878 } 879 880 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 881 public Builder addRootType() { 882 super.addRootType(); 883 return this; 884 } 885 886 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 887 public Builder addRootType(boolean value) { 888 super.addRootType(value); 889 return this; 890 } 891 892 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 893 public Builder keepNullProperties() { 894 super.keepNullProperties(); 895 return this; 896 } 897 898 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 899 public Builder keepNullProperties(boolean value) { 900 super.keepNullProperties(value); 901 return this; 902 } 903 904 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 905 public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) { 906 super.listener(value); 907 return this; 908 } 909 910 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 911 public Builder produces(String value) { 912 super.produces(value); 913 return this; 914 } 915 916 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 917 public Builder sortCollections() { 918 super.sortCollections(); 919 return this; 920 } 921 922 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 923 public Builder sortCollections(boolean value) { 924 super.sortCollections(value); 925 return this; 926 } 927 928 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 929 public Builder sortMaps() { 930 super.sortMaps(); 931 return this; 932 } 933 934 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 935 public Builder sortMaps(boolean value) { 936 super.sortMaps(value); 937 return this; 938 } 939 940 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 941 public Builder trimEmptyCollections() { 942 super.trimEmptyCollections(); 943 return this; 944 } 945 946 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 947 public Builder trimEmptyCollections(boolean value) { 948 super.trimEmptyCollections(value); 949 return this; 950 } 951 952 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 953 public Builder trimEmptyMaps() { 954 super.trimEmptyMaps(); 955 return this; 956 } 957 958 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 959 public Builder trimEmptyMaps(boolean value) { 960 super.trimEmptyMaps(value); 961 return this; 962 } 963 964 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 965 public Builder trimStrings() { 966 super.trimStrings(); 967 return this; 968 } 969 970 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 971 public Builder trimStrings(boolean value) { 972 super.trimStrings(value); 973 return this; 974 } 975 976 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 977 public Builder uriContext(UriContext value) { 978 super.uriContext(value); 979 return this; 980 } 981 982 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 983 public Builder uriRelativity(UriRelativity value) { 984 super.uriRelativity(value); 985 return this; 986 } 987 988 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 989 public Builder uriResolution(UriResolution value) { 990 super.uriResolution(value); 991 return this; 992 } 993 994 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 995 public Builder fileCharset(Charset value) { 996 super.fileCharset(value); 997 return this; 998 } 999 1000 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1001 public Builder maxIndent(int value) { 1002 super.maxIndent(value); 1003 return this; 1004 } 1005 1006 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1007 public Builder quoteChar(char value) { 1008 super.quoteChar(value); 1009 return this; 1010 } 1011 1012 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1013 public Builder quoteCharOverride(char value) { 1014 super.quoteCharOverride(value); 1015 return this; 1016 } 1017 1018 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1019 public Builder sq() { 1020 super.sq(); 1021 return this; 1022 } 1023 1024 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1025 public Builder streamCharset(Charset value) { 1026 super.streamCharset(value); 1027 return this; 1028 } 1029 1030 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1031 public Builder useWhitespace() { 1032 super.useWhitespace(); 1033 return this; 1034 } 1035 1036 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1037 public Builder useWhitespace(boolean value) { 1038 super.useWhitespace(value); 1039 return this; 1040 } 1041 1042 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1043 public Builder ws() { 1044 super.ws(); 1045 return this; 1046 } 1047 1048 // </FluentSetters> 1049 } 1050 1051 //------------------------------------------------------------------------------------------------------------------- 1052 // Instance 1053 //------------------------------------------------------------------------------------------------------------------- 1054 1055 final boolean addBeanTypesJson, escapeSolidus, simpleAttrs; 1056 1057 private final boolean addBeanTypes; 1058 private final Map<ClassMeta<?>,JsonClassMeta> jsonClassMetas = new ConcurrentHashMap<>(); 1059 private final Map<BeanPropertyMeta,JsonBeanPropertyMeta> jsonBeanPropertyMetas = new ConcurrentHashMap<>(); 1060 1061 private volatile JsonSchemaSerializer schemaSerializer; 1062 1063 /** 1064 * Constructor. 1065 * 1066 * @param builder The builder for this object. 1067 */ 1068 public JsonSerializer(Builder builder) { 1069 super(builder); 1070 addBeanTypesJson = builder.addBeanTypesJson; 1071 simpleAttrs = builder.simpleAttrs; 1072 escapeSolidus = builder.escapeSolidus; 1073 1074 addBeanTypes = addBeanTypesJson || super.isAddBeanTypes(); 1075 } 1076 1077 @Override /* Context */ 1078 public Builder copy() { 1079 return new Builder(this); 1080 } 1081 1082 @Override /* Context */ 1083 public JsonSerializerSession.Builder createSession() { 1084 return JsonSerializerSession.create(this); 1085 } 1086 1087 @Override /* Context */ 1088 public JsonSerializerSession getSession() { 1089 return createSession().build(); 1090 } 1091 1092 /** 1093 * Returns the schema serializer based on the settings of this serializer. 1094 * 1095 * <p> 1096 * Note that this method creates a builder initialized to all default settings, whereas {@link #copy()} copies 1097 * the settings of the object called on. 1098 * 1099 * @return The schema serializer. 1100 */ 1101 public JsonSchemaSerializer getSchemaSerializer() { 1102 if (schemaSerializer == null) 1103 schemaSerializer = JsonSchemaSerializer.create().beanContext(getBeanContext()).build(); 1104 return schemaSerializer; 1105 } 1106 1107 //----------------------------------------------------------------------------------------------------------------- 1108 // Extended metadata 1109 //----------------------------------------------------------------------------------------------------------------- 1110 1111 @Override /* JsonMetaProvider */ 1112 public JsonClassMeta getJsonClassMeta(ClassMeta<?> cm) { 1113 JsonClassMeta m = jsonClassMetas.get(cm); 1114 if (m == null) { 1115 m = new JsonClassMeta(cm, this); 1116 jsonClassMetas.put(cm, m); 1117 } 1118 return m; 1119 } 1120 1121 @Override /* JsonMetaProvider */ 1122 public JsonBeanPropertyMeta getJsonBeanPropertyMeta(BeanPropertyMeta bpm) { 1123 if (bpm == null) 1124 return JsonBeanPropertyMeta.DEFAULT; 1125 JsonBeanPropertyMeta m = jsonBeanPropertyMetas.get(bpm); 1126 if (m == null) { 1127 m = new JsonBeanPropertyMeta(bpm.getDelegateFor(), this); 1128 jsonBeanPropertyMetas.put(bpm, m); 1129 } 1130 return m; 1131 } 1132 1133 //----------------------------------------------------------------------------------------------------------------- 1134 // Properties 1135 //----------------------------------------------------------------------------------------------------------------- 1136 1137 /** 1138 * Add <js>"_type"</js> properties when needed. 1139 * 1140 * @see Builder#addBeanTypesJson() 1141 * @return 1142 * <jk>true</jk> if <js>"_type"</js> properties will be added to beans if their type cannot be inferred 1143 * through reflection. 1144 */ 1145 @Override 1146 protected final boolean isAddBeanTypes() { 1147 return addBeanTypes; 1148 } 1149 1150 /** 1151 * Prefix solidus <js>'/'</js> characters with escapes. 1152 * 1153 * @see Builder#escapeSolidus() 1154 * @return 1155 * <jk>true</jk> if solidus (e.g. slash) characters should be escaped. 1156 */ 1157 protected final boolean isEscapeSolidus() { 1158 return escapeSolidus; 1159 } 1160 1161 /** 1162 * Simple JSON mode. 1163 * 1164 * @see Builder#simpleAttrs() 1165 * @return 1166 * <jk>true</jk> if JSON attribute names will only be quoted when necessary. 1167 * <br>Otherwise, they are always quoted. 1168 */ 1169 protected final boolean isSimpleAttrs() { 1170 return simpleAttrs; 1171 } 1172 1173 //----------------------------------------------------------------------------------------------------------------- 1174 // Other methods 1175 //----------------------------------------------------------------------------------------------------------------- 1176 1177 @Override /* Context */ 1178 protected JsonMap properties() { 1179 return filteredMap("simpleAttrs", simpleAttrs, "escapeSolidus", escapeSolidus, "addBeanTypesJson", addBeanTypesJson); 1180 } 1181}