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 super(); 180 produces("application/json"); 181 accept("application/json,text/json"); 182 addBeanTypesJson = env("JsonSerializer.addBeanTypes", false); 183 escapeSolidus = env("JsonSerializer.escapeSolidus", false); 184 simpleAttrs = env("JsonSerializer.simpleAttrs", false); 185 } 186 187 /** 188 * Copy constructor. 189 * 190 * @param copyFrom The bean to copy from. 191 */ 192 protected Builder(JsonSerializer copyFrom) { 193 super(copyFrom); 194 addBeanTypesJson = copyFrom.addBeanTypesJson; 195 escapeSolidus = copyFrom.escapeSolidus; 196 simpleAttrs = copyFrom.simpleAttrs; 197 } 198 199 /** 200 * Copy constructor. 201 * 202 * @param copyFrom The builder to copy from. 203 */ 204 protected Builder(Builder copyFrom) { 205 super(copyFrom); 206 addBeanTypesJson = copyFrom.addBeanTypesJson; 207 escapeSolidus = copyFrom.escapeSolidus; 208 simpleAttrs = copyFrom.simpleAttrs; 209 } 210 211 @Override /* Context.Builder */ 212 public Builder copy() { 213 return new Builder(this); 214 } 215 216 @Override /* Context.Builder */ 217 public JsonSerializer build() { 218 return cache(CACHE).build(JsonSerializer.class); 219 } 220 221 @Override /* Context.Builder */ 222 public HashKey hashKey() { 223 return HashKey.of( 224 super.hashKey(), 225 addBeanTypesJson, 226 escapeSolidus, 227 simpleAttrs 228 ); 229 } 230 231 //----------------------------------------------------------------------------------------------------------------- 232 // Properties 233 //----------------------------------------------------------------------------------------------------------------- 234 235 /** 236 * Add <js>"_type"</js> properties when needed. 237 * 238 * <p> 239 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred 240 * through reflection. 241 * 242 * <p> 243 * When present, this value overrides the {@link org.apache.juneau.serializer.Serializer.Builder#addBeanTypes()} setting and is 244 * provided to customize the behavior of specific serializers in a {@link SerializerSet}. 245 * 246 * @return This object. 247 */ 248 @FluentSetter 249 public Builder addBeanTypesJson() { 250 return addBeanTypesJson(true); 251 } 252 253 /** 254 * Same as {@link #addBeanTypesJson()} but allows you to explicitly specify the value. 255 * 256 * @param value The value for this setting. 257 * @return This object. 258 */ 259 @FluentSetter 260 public Builder addBeanTypesJson(boolean value) { 261 addBeanTypesJson = value; 262 return this; 263 } 264 265 /** 266 * Prefix solidus <js>'/'</js> characters with escapes. 267 * 268 * <p> 269 * If enabled, solidus (e.g. slash) characters should be escaped. 270 * 271 * <p> 272 * The JSON specification allows for either format. 273 * <br>However, if you're embedding JSON in an HTML script tag, this setting prevents confusion when trying to serialize 274 * <xt><\/script></xt>. 275 * 276 * <h5 class='section'>Example:</h5> 277 * <p class='bjava'> 278 * <jc>// Create a JSON serializer that escapes solidus characters.</jc> 279 * WriterSerializer <jv>serializer</jv> = JsonSerializer 280 * .<jsm>create</jsm>() 281 * .simple() 282 * .escapeSolidus() 283 * .build(); 284 * 285 * <jc>// Produces: "{foo:'<\/bar>'"</jc> 286 * String <jv>json</jv> = <jv>serializer</jv>.serialize(JsonMap.<jsm>of</jsm>(<js>"foo"</js>, <js>"</bar>"</js>); 287 * </p> 288 * 289 * @return This object. 290 */ 291 @FluentSetter 292 public Builder escapeSolidus() { 293 return escapeSolidus(true); 294 } 295 296 /** 297 * Same as {@link #escapeSolidus()} but allows you to explicitly specify the value. 298 * 299 * @param value The value for this setting. 300 * @return This object. 301 */ 302 @FluentSetter 303 public Builder escapeSolidus(boolean value) { 304 escapeSolidus = value; 305 return this; 306 } 307 308 /** 309 * Simple JSON attributes mode. 310 * 311 * <p> 312 * If enabled, JSON attribute names will only be quoted when necessary. 313 * <br>Otherwise, they are always quoted. 314 * 315 * <p> 316 * Attributes do not need to be quoted when they conform to the following: 317 * <ol class='spaced-list'> 318 * <li>They start with an ASCII character or <js>'_'</js>. 319 * <li>They contain only ASCII characters or numbers or <js>'_'</js>. 320 * <li>They are not one of the following reserved words: 321 * <p class='bcode'> 322 * arguments, break, case, catch, class, const, continue, debugger, default, 323 * delete, do, else, enum, eval, export, extends, false, finally, for, function, 324 * if, implements, import, in, instanceof, interface, let, new, null, package, 325 * private, protected, public, return, static, super, switch, this, throw, 326 * true, try, typeof, var, void, while, with, undefined, yield 327 * </p> 328 * </ol> 329 * 330 * <h5 class='section'>Example:</h5> 331 * <p class='bjava'> 332 * <jc>// Create a JSON serializer in normal mode.</jc> 333 * WriterSerializer <jv>serializer1</jv> = JsonSerializer 334 * .<jsm>create</jsm>() 335 * .build(); 336 * 337 * <jc>// Create a JSON serializer in simple mode.</jc> 338 * WriterSerializer <jv>serializer2</jv> = JsonSerializer 339 * .<jsm>create</jsm>() 340 * .simpleAttrs() 341 * .build(); 342 * 343 * JsonMap <jv>myMap</jv> = JsonMap.<jsm>of</jsm>( 344 * <js>"foo"</js>, <js>"x1"</js>, 345 * <js>"_bar"</js>, <js>"x2"</js>, 346 * <js>" baz "</js>, <js>"x3"</js>, 347 * <js>"123"</js>, <js>"x4"</js>, 348 * <js>"return"</js>, <js>"x5"</js>, 349 * <js>""</js>, <js>"x6"</js> 350 * ); 351 * 352 * <jc>// Produces:</jc> 353 * <jc>// {</jc> 354 * <jc>// "foo": "x1"</jc> 355 * <jc>// "_bar": "x2"</jc> 356 * <jc>// " baz ": "x3"</jc> 357 * <jc>// "123": "x4"</jc> 358 * <jc>// "return": "x5"</jc> 359 * <jc>// "": "x6"</jc> 360 * <jc>// }</jc> 361 * String <jv>json1</jv> = <jv>serializer1</jv>.serialize(<jv>myMap</jv>); 362 * 363 * <jc>// Produces:</jc> 364 * <jc>// {</jc> 365 * <jc>// foo: "x1"</jc> 366 * <jc>// _bar: "x2"</jc> 367 * <jc>// " baz ": "x3"</jc> 368 * <jc>// "123": "x4"</jc> 369 * <jc>// "return": "x5"</jc> 370 * <jc>// "": "x6"</jc> 371 * <jc>// }</jc> 372 * String <jv>json2</jv> = <jv>serializer2</jv>.serialize(<jv>myMap</jv>); 373 * </p> 374 * 375 * @return This object. 376 */ 377 @FluentSetter 378 public Builder simpleAttrs() { 379 return simpleAttrs(true); 380 } 381 382 /** 383 * Same as {@link #simpleAttrs()} but allows you to explicitly specify the value. 384 * 385 * @param value The value for this setting. 386 * @return This object. 387 */ 388 @FluentSetter 389 public Builder simpleAttrs(boolean value) { 390 simpleAttrs = value; 391 return this; 392 } 393 394 /** 395 * Simple JSON mode and single quote. 396 * 397 * <p> 398 * Shortcut for calling <c>simple().sq()</c>. 399 * 400 * <h5 class='section'>See Also:</h5><ul> 401 * <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#quoteChar(char)} 402 * </ul> 403 * 404 * @return This object. 405 */ 406 @FluentSetter 407 public Builder json5() { 408 return simpleAttrs().sq(); 409 } 410 411 // <FluentSetters> 412 413 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 414 public Builder annotations(Annotation...values) { 415 super.annotations(values); 416 return this; 417 } 418 419 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 420 public Builder apply(AnnotationWorkList work) { 421 super.apply(work); 422 return this; 423 } 424 425 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 426 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 427 super.applyAnnotations(fromClasses); 428 return this; 429 } 430 431 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 432 public Builder applyAnnotations(Method...fromMethods) { 433 super.applyAnnotations(fromMethods); 434 return this; 435 } 436 437 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 438 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 439 super.cache(value); 440 return this; 441 } 442 443 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 444 public Builder debug() { 445 super.debug(); 446 return this; 447 } 448 449 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 450 public Builder debug(boolean value) { 451 super.debug(value); 452 return this; 453 } 454 455 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 456 public Builder impl(Context value) { 457 super.impl(value); 458 return this; 459 } 460 461 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 462 public Builder type(Class<? extends org.apache.juneau.Context> value) { 463 super.type(value); 464 return this; 465 } 466 467 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 468 public Builder beanClassVisibility(Visibility value) { 469 super.beanClassVisibility(value); 470 return this; 471 } 472 473 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 474 public Builder beanConstructorVisibility(Visibility value) { 475 super.beanConstructorVisibility(value); 476 return this; 477 } 478 479 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 480 public Builder beanContext(BeanContext value) { 481 super.beanContext(value); 482 return this; 483 } 484 485 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 486 public Builder beanContext(BeanContext.Builder value) { 487 super.beanContext(value); 488 return this; 489 } 490 491 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 492 public Builder beanDictionary(java.lang.Class<?>...values) { 493 super.beanDictionary(values); 494 return this; 495 } 496 497 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 498 public Builder beanFieldVisibility(Visibility value) { 499 super.beanFieldVisibility(value); 500 return this; 501 } 502 503 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 504 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 505 super.beanInterceptor(on, value); 506 return this; 507 } 508 509 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 510 public Builder beanMapPutReturnsOldValue() { 511 super.beanMapPutReturnsOldValue(); 512 return this; 513 } 514 515 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 516 public Builder beanMethodVisibility(Visibility value) { 517 super.beanMethodVisibility(value); 518 return this; 519 } 520 521 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 522 public Builder beanProperties(Map<String,Object> values) { 523 super.beanProperties(values); 524 return this; 525 } 526 527 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 528 public Builder beanProperties(Class<?> beanClass, String properties) { 529 super.beanProperties(beanClass, properties); 530 return this; 531 } 532 533 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 534 public Builder beanProperties(String beanClassName, String properties) { 535 super.beanProperties(beanClassName, properties); 536 return this; 537 } 538 539 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 540 public Builder beanPropertiesExcludes(Map<String,Object> values) { 541 super.beanPropertiesExcludes(values); 542 return this; 543 } 544 545 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 546 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 547 super.beanPropertiesExcludes(beanClass, properties); 548 return this; 549 } 550 551 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 552 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 553 super.beanPropertiesExcludes(beanClassName, properties); 554 return this; 555 } 556 557 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 558 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 559 super.beanPropertiesReadOnly(values); 560 return this; 561 } 562 563 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 564 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 565 super.beanPropertiesReadOnly(beanClass, properties); 566 return this; 567 } 568 569 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 570 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 571 super.beanPropertiesReadOnly(beanClassName, properties); 572 return this; 573 } 574 575 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 576 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 577 super.beanPropertiesWriteOnly(values); 578 return this; 579 } 580 581 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 582 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 583 super.beanPropertiesWriteOnly(beanClass, properties); 584 return this; 585 } 586 587 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 588 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 589 super.beanPropertiesWriteOnly(beanClassName, properties); 590 return this; 591 } 592 593 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 594 public Builder beansRequireDefaultConstructor() { 595 super.beansRequireDefaultConstructor(); 596 return this; 597 } 598 599 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 600 public Builder beansRequireSerializable() { 601 super.beansRequireSerializable(); 602 return this; 603 } 604 605 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 606 public Builder beansRequireSettersForGetters() { 607 super.beansRequireSettersForGetters(); 608 return this; 609 } 610 611 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 612 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 613 super.dictionaryOn(on, values); 614 return this; 615 } 616 617 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 618 public Builder disableBeansRequireSomeProperties() { 619 super.disableBeansRequireSomeProperties(); 620 return this; 621 } 622 623 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 624 public Builder disableIgnoreMissingSetters() { 625 super.disableIgnoreMissingSetters(); 626 return this; 627 } 628 629 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 630 public Builder disableIgnoreTransientFields() { 631 super.disableIgnoreTransientFields(); 632 return this; 633 } 634 635 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 636 public Builder disableIgnoreUnknownNullBeanProperties() { 637 super.disableIgnoreUnknownNullBeanProperties(); 638 return this; 639 } 640 641 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 642 public Builder disableInterfaceProxies() { 643 super.disableInterfaceProxies(); 644 return this; 645 } 646 647 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 648 public <T> Builder example(Class<T> pojoClass, T o) { 649 super.example(pojoClass, o); 650 return this; 651 } 652 653 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 654 public <T> Builder example(Class<T> pojoClass, String json) { 655 super.example(pojoClass, json); 656 return this; 657 } 658 659 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 660 public Builder findFluentSetters() { 661 super.findFluentSetters(); 662 return this; 663 } 664 665 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 666 public Builder findFluentSetters(Class<?> on) { 667 super.findFluentSetters(on); 668 return this; 669 } 670 671 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 672 public Builder ignoreInvocationExceptionsOnGetters() { 673 super.ignoreInvocationExceptionsOnGetters(); 674 return this; 675 } 676 677 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 678 public Builder ignoreInvocationExceptionsOnSetters() { 679 super.ignoreInvocationExceptionsOnSetters(); 680 return this; 681 } 682 683 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 684 public Builder ignoreUnknownBeanProperties() { 685 super.ignoreUnknownBeanProperties(); 686 return this; 687 } 688 689 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 690 public Builder ignoreUnknownEnumValues() { 691 super.ignoreUnknownEnumValues(); 692 return this; 693 } 694 695 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 696 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 697 super.implClass(interfaceClass, implClass); 698 return this; 699 } 700 701 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 702 public Builder implClasses(Map<Class<?>,Class<?>> values) { 703 super.implClasses(values); 704 return this; 705 } 706 707 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 708 public Builder interfaceClass(Class<?> on, Class<?> value) { 709 super.interfaceClass(on, value); 710 return this; 711 } 712 713 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 714 public Builder interfaces(java.lang.Class<?>...value) { 715 super.interfaces(value); 716 return this; 717 } 718 719 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 720 public Builder locale(Locale value) { 721 super.locale(value); 722 return this; 723 } 724 725 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 726 public Builder mediaType(MediaType value) { 727 super.mediaType(value); 728 return this; 729 } 730 731 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 732 public Builder notBeanClasses(java.lang.Class<?>...values) { 733 super.notBeanClasses(values); 734 return this; 735 } 736 737 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 738 public Builder notBeanPackages(String...values) { 739 super.notBeanPackages(values); 740 return this; 741 } 742 743 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 744 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 745 super.propertyNamer(value); 746 return this; 747 } 748 749 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 750 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 751 super.propertyNamer(on, value); 752 return this; 753 } 754 755 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 756 public Builder sortProperties() { 757 super.sortProperties(); 758 return this; 759 } 760 761 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 762 public Builder sortProperties(java.lang.Class<?>...on) { 763 super.sortProperties(on); 764 return this; 765 } 766 767 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 768 public Builder stopClass(Class<?> on, Class<?> value) { 769 super.stopClass(on, value); 770 return this; 771 } 772 773 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 774 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 775 super.swap(normalClass, swappedClass, swapFunction); 776 return this; 777 } 778 779 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 780 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 781 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 782 return this; 783 } 784 785 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 786 public Builder swaps(java.lang.Class<?>...values) { 787 super.swaps(values); 788 return this; 789 } 790 791 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 792 public Builder timeZone(TimeZone value) { 793 super.timeZone(value); 794 return this; 795 } 796 797 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 798 public Builder typeName(Class<?> on, String value) { 799 super.typeName(on, value); 800 return this; 801 } 802 803 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 804 public Builder typePropertyName(String value) { 805 super.typePropertyName(value); 806 return this; 807 } 808 809 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 810 public Builder typePropertyName(Class<?> on, String value) { 811 super.typePropertyName(on, value); 812 return this; 813 } 814 815 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 816 public Builder useEnumNames() { 817 super.useEnumNames(); 818 return this; 819 } 820 821 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 822 public Builder useJavaBeanIntrospector() { 823 super.useJavaBeanIntrospector(); 824 return this; 825 } 826 827 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 828 public Builder detectRecursions() { 829 super.detectRecursions(); 830 return this; 831 } 832 833 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 834 public Builder detectRecursions(boolean value) { 835 super.detectRecursions(value); 836 return this; 837 } 838 839 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 840 public Builder ignoreRecursions() { 841 super.ignoreRecursions(); 842 return this; 843 } 844 845 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 846 public Builder ignoreRecursions(boolean value) { 847 super.ignoreRecursions(value); 848 return this; 849 } 850 851 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 852 public Builder initialDepth(int value) { 853 super.initialDepth(value); 854 return this; 855 } 856 857 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 858 public Builder maxDepth(int value) { 859 super.maxDepth(value); 860 return this; 861 } 862 863 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 864 public Builder accept(String value) { 865 super.accept(value); 866 return this; 867 } 868 869 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 870 public Builder addBeanTypes() { 871 super.addBeanTypes(); 872 return this; 873 } 874 875 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 876 public Builder addBeanTypes(boolean value) { 877 super.addBeanTypes(value); 878 return this; 879 } 880 881 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 882 public Builder addRootType() { 883 super.addRootType(); 884 return this; 885 } 886 887 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 888 public Builder addRootType(boolean value) { 889 super.addRootType(value); 890 return this; 891 } 892 893 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 894 public Builder keepNullProperties() { 895 super.keepNullProperties(); 896 return this; 897 } 898 899 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 900 public Builder keepNullProperties(boolean value) { 901 super.keepNullProperties(value); 902 return this; 903 } 904 905 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 906 public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) { 907 super.listener(value); 908 return this; 909 } 910 911 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 912 public Builder produces(String value) { 913 super.produces(value); 914 return this; 915 } 916 917 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 918 public Builder sortCollections() { 919 super.sortCollections(); 920 return this; 921 } 922 923 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 924 public Builder sortCollections(boolean value) { 925 super.sortCollections(value); 926 return this; 927 } 928 929 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 930 public Builder sortMaps() { 931 super.sortMaps(); 932 return this; 933 } 934 935 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 936 public Builder sortMaps(boolean value) { 937 super.sortMaps(value); 938 return this; 939 } 940 941 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 942 public Builder trimEmptyCollections() { 943 super.trimEmptyCollections(); 944 return this; 945 } 946 947 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 948 public Builder trimEmptyCollections(boolean value) { 949 super.trimEmptyCollections(value); 950 return this; 951 } 952 953 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 954 public Builder trimEmptyMaps() { 955 super.trimEmptyMaps(); 956 return this; 957 } 958 959 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 960 public Builder trimEmptyMaps(boolean value) { 961 super.trimEmptyMaps(value); 962 return this; 963 } 964 965 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 966 public Builder trimStrings() { 967 super.trimStrings(); 968 return this; 969 } 970 971 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 972 public Builder trimStrings(boolean value) { 973 super.trimStrings(value); 974 return this; 975 } 976 977 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 978 public Builder uriContext(UriContext value) { 979 super.uriContext(value); 980 return this; 981 } 982 983 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 984 public Builder uriRelativity(UriRelativity value) { 985 super.uriRelativity(value); 986 return this; 987 } 988 989 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 990 public Builder uriResolution(UriResolution value) { 991 super.uriResolution(value); 992 return this; 993 } 994 995 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 996 public Builder fileCharset(Charset value) { 997 super.fileCharset(value); 998 return this; 999 } 1000 1001 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1002 public Builder maxIndent(int value) { 1003 super.maxIndent(value); 1004 return this; 1005 } 1006 1007 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1008 public Builder quoteChar(char value) { 1009 super.quoteChar(value); 1010 return this; 1011 } 1012 1013 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1014 public Builder quoteCharOverride(char value) { 1015 super.quoteCharOverride(value); 1016 return this; 1017 } 1018 1019 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1020 public Builder sq() { 1021 super.sq(); 1022 return this; 1023 } 1024 1025 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1026 public Builder streamCharset(Charset value) { 1027 super.streamCharset(value); 1028 return this; 1029 } 1030 1031 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1032 public Builder useWhitespace() { 1033 super.useWhitespace(); 1034 return this; 1035 } 1036 1037 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1038 public Builder useWhitespace(boolean value) { 1039 super.useWhitespace(value); 1040 return this; 1041 } 1042 1043 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1044 public Builder ws() { 1045 super.ws(); 1046 return this; 1047 } 1048 1049 // </FluentSetters> 1050 } 1051 1052 //------------------------------------------------------------------------------------------------------------------- 1053 // Instance 1054 //------------------------------------------------------------------------------------------------------------------- 1055 1056 final boolean addBeanTypesJson, escapeSolidus, simpleAttrs; 1057 1058 private final boolean addBeanTypes; 1059 private final Map<ClassMeta<?>,JsonClassMeta> jsonClassMetas = new ConcurrentHashMap<>(); 1060 private final Map<BeanPropertyMeta,JsonBeanPropertyMeta> jsonBeanPropertyMetas = new ConcurrentHashMap<>(); 1061 1062 private volatile JsonSchemaSerializer schemaSerializer; 1063 1064 /** 1065 * Constructor. 1066 * 1067 * @param builder The builder for this object. 1068 */ 1069 public JsonSerializer(Builder builder) { 1070 super(builder); 1071 addBeanTypesJson = builder.addBeanTypesJson; 1072 simpleAttrs = builder.simpleAttrs; 1073 escapeSolidus = builder.escapeSolidus; 1074 1075 addBeanTypes = addBeanTypesJson || super.isAddBeanTypes(); 1076 } 1077 1078 @Override /* Context */ 1079 public Builder copy() { 1080 return new Builder(this); 1081 } 1082 1083 @Override /* Context */ 1084 public JsonSerializerSession.Builder createSession() { 1085 return JsonSerializerSession.create(this); 1086 } 1087 1088 @Override /* Context */ 1089 public JsonSerializerSession getSession() { 1090 return createSession().build(); 1091 } 1092 1093 /** 1094 * Returns the schema serializer based on the settings of this serializer. 1095 * 1096 * <p> 1097 * Note that this method creates a builder initialized to all default settings, whereas {@link #copy()} copies 1098 * the settings of the object called on. 1099 * 1100 * @return The schema serializer. 1101 */ 1102 public JsonSchemaSerializer getSchemaSerializer() { 1103 if (schemaSerializer == null) 1104 schemaSerializer = JsonSchemaSerializer.create().beanContext(getBeanContext()).build(); 1105 return schemaSerializer; 1106 } 1107 1108 //----------------------------------------------------------------------------------------------------------------- 1109 // Extended metadata 1110 //----------------------------------------------------------------------------------------------------------------- 1111 1112 @Override /* JsonMetaProvider */ 1113 public JsonClassMeta getJsonClassMeta(ClassMeta<?> cm) { 1114 JsonClassMeta m = jsonClassMetas.get(cm); 1115 if (m == null) { 1116 m = new JsonClassMeta(cm, this); 1117 jsonClassMetas.put(cm, m); 1118 } 1119 return m; 1120 } 1121 1122 @Override /* JsonMetaProvider */ 1123 public JsonBeanPropertyMeta getJsonBeanPropertyMeta(BeanPropertyMeta bpm) { 1124 if (bpm == null) 1125 return JsonBeanPropertyMeta.DEFAULT; 1126 JsonBeanPropertyMeta m = jsonBeanPropertyMetas.get(bpm); 1127 if (m == null) { 1128 m = new JsonBeanPropertyMeta(bpm.getDelegateFor(), this); 1129 jsonBeanPropertyMetas.put(bpm, m); 1130 } 1131 return m; 1132 } 1133 1134 //----------------------------------------------------------------------------------------------------------------- 1135 // Properties 1136 //----------------------------------------------------------------------------------------------------------------- 1137 1138 /** 1139 * Add <js>"_type"</js> properties when needed. 1140 * 1141 * @see Builder#addBeanTypesJson() 1142 * @return 1143 * <jk>true</jk> if <js>"_type"</js> properties will be added to beans if their type cannot be inferred 1144 * through reflection. 1145 */ 1146 @Override 1147 protected final boolean isAddBeanTypes() { 1148 return addBeanTypes; 1149 } 1150 1151 /** 1152 * Prefix solidus <js>'/'</js> characters with escapes. 1153 * 1154 * @see Builder#escapeSolidus() 1155 * @return 1156 * <jk>true</jk> if solidus (e.g. slash) characters should be escaped. 1157 */ 1158 protected final boolean isEscapeSolidus() { 1159 return escapeSolidus; 1160 } 1161 1162 /** 1163 * Simple JSON mode. 1164 * 1165 * @see Builder#simpleAttrs() 1166 * @return 1167 * <jk>true</jk> if JSON attribute names will only be quoted when necessary. 1168 * <br>Otherwise, they are always quoted. 1169 */ 1170 protected final boolean isSimpleAttrs() { 1171 return simpleAttrs; 1172 } 1173 1174 //----------------------------------------------------------------------------------------------------------------- 1175 // Other methods 1176 //----------------------------------------------------------------------------------------------------------------- 1177 1178 @Override /* Context */ 1179 protected JsonMap properties() { 1180 return filteredMap("simpleAttrs", simpleAttrs, "escapeSolidus", escapeSolidus, "addBeanTypesJson", addBeanTypesJson); 1181 } 1182}