001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.serializer; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.CollectionUtils.*; 021import static org.apache.juneau.commons.utils.StringUtils.*; 022import static org.apache.juneau.commons.utils.ThrowableUtils.*; 023import static org.apache.juneau.commons.utils.Utils.*; 024 025import java.io.*; 026import java.lang.annotation.*; 027import java.util.*; 028import java.util.function.*; 029 030import org.apache.juneau.*; 031import org.apache.juneau.annotation.*; 032import org.apache.juneau.commons.collections.*; 033import org.apache.juneau.commons.function.*; 034import org.apache.juneau.commons.reflect.*; 035import org.apache.juneau.soap.*; 036 037/** 038 * Parent class for all Juneau serializers. 039 * 040 * <h5 class='topic'>Description</h5> 041 * <p> 042 * Base serializer class that serves as the parent class for all serializers. 043 * 044 * <p> 045 * The purpose of this class is: 046 * <ul> 047 * <li>Maintain a read-only configuration state of a serializer. 048 * <li>Create session objects used for serializing POJOs (i.e. {@link SerializerSession}). 049 * <li>Provide convenience methods for serializing POJOs without having to construct session objects. 050 * </ul> 051 * 052 * <p> 053 * Subclasses should (but are not required to) extend directly from {@link OutputStreamSerializer} or {@link WriterSerializer} depending on 054 * whether it's a stream or character based serializer. 055 * 056 * <p> 057 * Subclasses must implement parsing via one of the following methods: 058 * <ul class='javatree'> 059 * <li class='jmp'>{@link #doSerialize(SerializerSession, SerializerPipe, Object)} 060 * <li class='jmp'>{@link SerializerSession#doSerialize(SerializerPipe, Object)} 061 * </ul> 062 * <br> 063 * 064 * <h5 class='section'>Notes:</h5><ul> 065 * <li class='note'>This class is thread safe and reusable. 066 * </ul> 067 * 068 * <h5 class='section'>See Also:</h5><ul> 069 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a> 070 071 * </ul> 072 */ 073public class Serializer extends BeanTraverseContext { 074 /** 075 * Builder class. 076 */ 077 public static class Builder extends BeanTraverseContext.Builder { 078 079 private boolean addBeanTypes; 080 private boolean addRootType; 081 private boolean keepNullProperties; 082 private boolean sortCollections; 083 private boolean sortMaps; 084 private boolean trimEmptyCollections; 085 private boolean trimEmptyMaps; 086 private boolean trimStrings; 087 private Class<? extends SerializerListener> listener; 088 private String accept; 089 private String produces; 090 private UriContext uriContext; 091 private UriRelativity uriRelativity; 092 private UriResolution uriResolution; 093 094 /** 095 * Constructor, default settings. 096 */ 097 protected Builder() { 098 produces = null; 099 accept = null; 100 addBeanTypes = env("Serializer.addBeanTypes", false); 101 addRootType = env("Serializer.addRootType", false); 102 keepNullProperties = env("Serializer.keepNullProperties", false); 103 sortCollections = env("Serializer.sortCollections", false); 104 sortMaps = env("Serializer.sortMaps", false); 105 trimEmptyCollections = env("Serializer.trimEmptyCollections", false); 106 trimEmptyMaps = env("Serializer.trimEmptyMaps", false); 107 trimStrings = env("Serializer.trimStrings", false); 108 uriContext = UriContext.DEFAULT; 109 uriRelativity = UriRelativity.RESOURCE; 110 uriResolution = UriResolution.NONE; 111 listener = null; 112 } 113 114 /** 115 * Copy constructor. 116 * 117 * @param copyFrom The builder to copy from. 118 * <br>Cannot be <jk>null</jk>. 119 */ 120 protected Builder(Builder copyFrom) { 121 super(assertArgNotNull("copyFrom", copyFrom)); 122 produces = copyFrom.produces; 123 accept = copyFrom.accept; 124 addBeanTypes = copyFrom.addBeanTypes; 125 addRootType = copyFrom.addRootType; 126 keepNullProperties = copyFrom.keepNullProperties; 127 sortCollections = copyFrom.sortCollections; 128 sortMaps = copyFrom.sortMaps; 129 trimEmptyCollections = copyFrom.trimEmptyCollections; 130 trimEmptyMaps = copyFrom.trimEmptyMaps; 131 trimStrings = copyFrom.trimStrings; 132 uriContext = copyFrom.uriContext; 133 uriRelativity = copyFrom.uriRelativity; 134 uriResolution = copyFrom.uriResolution; 135 listener = copyFrom.listener; 136 } 137 138 /** 139 * Copy constructor. 140 * 141 * @param copyFrom The bean to copy from. 142 * <br>Cannot be <jk>null</jk>. 143 */ 144 protected Builder(Serializer copyFrom) { 145 super(assertArgNotNull("copyFrom", copyFrom)); 146 produces = copyFrom.produces; 147 accept = copyFrom.accept; 148 addBeanTypes = copyFrom.addBeanTypes; 149 addRootType = copyFrom.addRootType; 150 keepNullProperties = copyFrom.keepNullProperties; 151 sortCollections = copyFrom.sortCollections; 152 sortMaps = copyFrom.sortMaps; 153 trimEmptyCollections = copyFrom.trimEmptyCollections; 154 trimEmptyMaps = copyFrom.trimEmptyMaps; 155 trimStrings = copyFrom.trimStrings; 156 uriContext = copyFrom.getUriContext(); 157 uriRelativity = copyFrom.getUriRelativity(); 158 uriResolution = copyFrom.getUriResolution(); 159 listener = copyFrom.listener; 160 } 161 162 /** 163 * Specifies the accept media types that the serializer can handle. 164 * 165 * <p> 166 * Can contain meta-characters per the <c>media-type</c> specification of <a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC2616/14.1</a> 167 * <p> 168 * If empty, then assumes the only media type supported is <c>produces</c>. 169 * <p> 170 * For example, if this serializer produces <js>"application/json"</js> but should handle media types of 171 * <js>"application/json"</js> and <js>"text/json"</js>, then the arguments should be: 172 * <p class='bjava'> 173 * <jv>builder</jv>.produces(<js>"application/json"</js>); 174 * <jv>builder</jv>.accept(<js>"application/json,text/json"</js>); 175 * </p> 176 * <p> 177 * The accept value can also contain q-values. 178 * 179 * @param value The value for this setting. 180 * <br>Can be <jk>null</jk> (will default to the value specified by {@link #produces(String)}). 181 * @return This object. 182 */ 183 public Builder accept(String value) { 184 accept = value; 185 return this; 186 } 187 188 /** 189 * Add <js>"_type"</js> properties when needed. 190 * 191 * <p> 192 * When enabled, <js>"_type"</js> properties will be added to beans if their type cannot be inferred 193 * through reflection. 194 * 195 * <p> 196 * This is used to recreate the correct objects during parsing if the object types cannot be inferred. 197 * <br>For example, when serializing a <c>Map<String,Object></c> field where the bean class cannot be determined from 198 * the type of the values. 199 * 200 * <p> 201 * Note the differences between the following settings: 202 * <ul class='javatree'> 203 * <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node. 204 * <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes. 205 * </ul> 206 * 207 * <h5 class='section'>Example:</h5> 208 * <p class='bjava'> 209 * <jc>// Create a serializer that adds _type to nodes.</jc> 210 * WriterSerializer <jv>serializer</jv> = JsonSerializer 211 * .<jsm>create</jsm>() 212 * .addBeanTypes() 213 * .build(); 214 * 215 * <jc>// Our map of beans to serialize.</jc> 216 * <ja>@Bean</ja>(typeName=<js>"mybean"</js>) 217 * <jk>public class</jk> MyBean { 218 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 219 * } 220 * JsonMap <jv>myMap</jv> = JsonMap.of(<js>"foo"</js>, <jk>new</jk> MyBean()); 221 * 222 * <jc>// Will contain: {"foo":{"_type":"mybean","foo":"bar"}}</jc> 223 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>myMap</jv>); 224 * </p> 225 * 226 * @return This object. 227 */ 228 public Builder addBeanTypes() { 229 return addBeanTypes(true); 230 } 231 232 /** 233 * Same as {@link #addBeanTypes()} but allows you to explicitly specify the value. 234 * 235 * @param value The value for this setting. 236 * @return This object. 237 */ 238 public Builder addBeanTypes(boolean value) { 239 addBeanTypes = value; 240 return this; 241 } 242 243 /** 244 * Add type attribute to root nodes. 245 * 246 * <p> 247 * When enabled, <js>"_type"</js> properties will be added to top-level beans. 248 * 249 * <p> 250 * When disabled, it is assumed that the parser knows the exact Java POJO type being parsed, and therefore top-level 251 * type information that might normally be included to determine the data type will not be serialized. 252 * 253 * <p> 254 * For example, when serializing a top-level POJO with a {@link Bean#typeName() @Bean(typeName)} value, a 255 * <js>'_type'</js> attribute will only be added when this setting is enabled. 256 * 257 * <p> 258 * Note the differences between the following settings: 259 * <ul class='javatree'> 260 * <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node. 261 * <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes. 262 * </ul> 263 * 264 * <h5 class='section'>Example:</h5> 265 * <p class='bjava'> 266 * <jc>// Create a serializer that adds _type to root node.</jc> 267 * WriterSerializer <jv>serializer</jv>= JsonSerializer 268 * .<jsm>create</jsm>() 269 * .addRootType() 270 * .build(); 271 * 272 * <jc>// Our bean to serialize.</jc> 273 * <ja>@Bean</ja>(typeName=<js>"mybean"</js>) 274 * <jk>public class</jk> MyBean { 275 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 276 * } 277 * 278 * <jc>// Will contain: {"_type":"mybean","foo":"bar"}</jc> 279 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 280 * </p> 281 * 282 * @return This object. 283 */ 284 public Builder addRootType() { 285 return addRootType(true); 286 } 287 288 /** 289 * Same as {@link #addRootType()} but allows you to explicitly specify the value. 290 * 291 * @param value The value for this setting. 292 * @return This object. 293 */ 294 public Builder addRootType(boolean value) { 295 addRootType = value; 296 return this; 297 } 298 299 @Override /* Overridden from Builder */ 300 public Builder annotations(Annotation...values) { 301 super.annotations(values); 302 return this; 303 } 304 305 @Override /* Overridden from Builder */ 306 public Builder apply(AnnotationWorkList work) { 307 super.apply(work); 308 return this; 309 } 310 311 @Override /* Overridden from Builder */ 312 public Builder applyAnnotations(Class<?>...from) { 313 super.applyAnnotations(from); 314 return this; 315 } 316 317 @Override /* Overridden from Builder */ 318 public Builder applyAnnotations(Object...from) { 319 super.applyAnnotations(from); 320 return this; 321 } 322 323 @Override /* Overridden from Builder */ 324 public Builder beanClassVisibility(Visibility value) { 325 super.beanClassVisibility(value); 326 return this; 327 } 328 329 @Override /* Overridden from Builder */ 330 public Builder beanConstructorVisibility(Visibility value) { 331 super.beanConstructorVisibility(value); 332 return this; 333 } 334 335 @Override /* Overridden from Builder */ 336 public Builder beanContext(BeanContext value) { 337 super.beanContext(value); 338 return this; 339 } 340 341 @Override /* Overridden from Builder */ 342 public Builder beanContext(BeanContext.Builder value) { 343 super.beanContext(value); 344 return this; 345 } 346 347 @Override /* Overridden from Builder */ 348 public Builder beanDictionary(java.lang.Class<?>...values) { 349 super.beanDictionary(values); 350 return this; 351 } 352 353 @Override /* Overridden from Builder */ 354 public Builder beanFieldVisibility(Visibility value) { 355 super.beanFieldVisibility(value); 356 return this; 357 } 358 359 @Override /* Overridden from Builder */ 360 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 361 super.beanInterceptor(on, value); 362 return this; 363 } 364 365 @Override /* Overridden from Builder */ 366 public Builder beanMapPutReturnsOldValue() { 367 super.beanMapPutReturnsOldValue(); 368 return this; 369 } 370 371 @Override /* Overridden from Builder */ 372 public Builder beanMethodVisibility(Visibility value) { 373 super.beanMethodVisibility(value); 374 return this; 375 } 376 377 @Override /* Overridden from Builder */ 378 public Builder beanProperties(Class<?> beanClass, String properties) { 379 super.beanProperties(beanClass, properties); 380 return this; 381 } 382 383 @Override /* Overridden from Builder */ 384 public Builder beanProperties(Map<String,Object> values) { 385 super.beanProperties(values); 386 return this; 387 } 388 389 @Override /* Overridden from Builder */ 390 public Builder beanProperties(String beanClassName, String properties) { 391 super.beanProperties(beanClassName, properties); 392 return this; 393 } 394 395 @Override /* Overridden from Builder */ 396 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 397 super.beanPropertiesExcludes(beanClass, properties); 398 return this; 399 } 400 401 @Override /* Overridden from Builder */ 402 public Builder beanPropertiesExcludes(Map<String,Object> values) { 403 super.beanPropertiesExcludes(values); 404 return this; 405 } 406 407 @Override /* Overridden from Builder */ 408 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 409 super.beanPropertiesExcludes(beanClassName, properties); 410 return this; 411 } 412 413 @Override /* Overridden from Builder */ 414 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 415 super.beanPropertiesReadOnly(beanClass, properties); 416 return this; 417 } 418 419 @Override /* Overridden from Builder */ 420 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 421 super.beanPropertiesReadOnly(values); 422 return this; 423 } 424 425 @Override /* Overridden from Builder */ 426 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 427 super.beanPropertiesReadOnly(beanClassName, properties); 428 return this; 429 } 430 431 @Override /* Overridden from Builder */ 432 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 433 super.beanPropertiesWriteOnly(beanClass, properties); 434 return this; 435 } 436 437 @Override /* Overridden from Builder */ 438 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 439 super.beanPropertiesWriteOnly(values); 440 return this; 441 } 442 443 @Override /* Overridden from Builder */ 444 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 445 super.beanPropertiesWriteOnly(beanClassName, properties); 446 return this; 447 } 448 449 @Override /* Overridden from Builder */ 450 public Builder beansRequireDefaultConstructor() { 451 super.beansRequireDefaultConstructor(); 452 return this; 453 } 454 455 @Override /* Overridden from Builder */ 456 public Builder beansRequireSerializable() { 457 super.beansRequireSerializable(); 458 return this; 459 } 460 461 @Override /* Overridden from Builder */ 462 public Builder beansRequireSettersForGetters() { 463 super.beansRequireSettersForGetters(); 464 return this; 465 } 466 467 @Override /* Overridden from Context.Builder */ 468 public Serializer build() { 469 return build(Serializer.class); 470 } 471 472 @Override /* Overridden from Builder */ 473 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 474 super.cache(value); 475 return this; 476 } 477 478 @Override /* Overridden from Context.Builder */ 479 public Builder copy() { 480 return new Builder(this); 481 } 482 483 @Override /* Overridden from Builder */ 484 public Builder debug() { 485 super.debug(); 486 return this; 487 } 488 489 @Override /* Overridden from Builder */ 490 public Builder debug(boolean value) { 491 super.debug(value); 492 return this; 493 } 494 495 @Override /* Overridden from Builder */ 496 public Builder detectRecursions() { 497 super.detectRecursions(); 498 return this; 499 } 500 501 @Override /* Overridden from Builder */ 502 public Builder detectRecursions(boolean value) { 503 super.detectRecursions(value); 504 return this; 505 } 506 507 @Override /* Overridden from Builder */ 508 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 509 super.dictionaryOn(on, values); 510 return this; 511 } 512 513 @Override /* Overridden from Builder */ 514 public Builder disableBeansRequireSomeProperties() { 515 super.disableBeansRequireSomeProperties(); 516 return this; 517 } 518 519 @Override /* Overridden from Builder */ 520 public Builder disableIgnoreMissingSetters() { 521 super.disableIgnoreMissingSetters(); 522 return this; 523 } 524 525 @Override /* Overridden from Builder */ 526 public Builder disableIgnoreTransientFields() { 527 super.disableIgnoreTransientFields(); 528 return this; 529 } 530 531 @Override /* Overridden from Builder */ 532 public Builder disableIgnoreUnknownNullBeanProperties() { 533 super.disableIgnoreUnknownNullBeanProperties(); 534 return this; 535 } 536 537 @Override /* Overridden from Builder */ 538 public Builder disableInterfaceProxies() { 539 super.disableInterfaceProxies(); 540 return this; 541 } 542 543 @Override /* Overridden from Builder */ 544 public <T> Builder example(Class<T> pojoClass, String json) { 545 super.example(pojoClass, json); 546 return this; 547 } 548 549 @Override /* Overridden from Builder */ 550 public <T> Builder example(Class<T> pojoClass, T o) { 551 super.example(pojoClass, o); 552 return this; 553 } 554 555 @Override /* Overridden from Builder */ 556 public Builder findFluentSetters() { 557 super.findFluentSetters(); 558 return this; 559 } 560 561 @Override /* Overridden from Builder */ 562 public Builder findFluentSetters(Class<?> on) { 563 super.findFluentSetters(on); 564 return this; 565 } 566 567 /** 568 * Returns the current value for the 'accept' property. 569 * 570 * @return The current value for the 'accept' property. 571 */ 572 public String getAccept() { return accept; } 573 574 /** 575 * Returns the current value for the 'produces' property. 576 * 577 * @return The current value for the 'produces' property. 578 */ 579 public String getProduces() { return produces; } 580 581 @Override /* Overridden from Context.Builder */ 582 public HashKey hashKey() { 583 // @formatter:off 584 return HashKey.of( 585 super.hashKey(), 586 produces, 587 accept, 588 addBeanTypes, 589 addRootType, 590 keepNullProperties, 591 sortCollections, 592 sortMaps, 593 trimEmptyCollections, 594 trimEmptyMaps, 595 trimStrings, 596 uriContext, 597 uriRelativity, 598 uriResolution, 599 listener 600 ); 601 // @formatter:on 602 } 603 604 @Override /* Overridden from Builder */ 605 public Builder ignoreInvocationExceptionsOnGetters() { 606 super.ignoreInvocationExceptionsOnGetters(); 607 return this; 608 } 609 610 @Override /* Overridden from Builder */ 611 public Builder ignoreInvocationExceptionsOnSetters() { 612 super.ignoreInvocationExceptionsOnSetters(); 613 return this; 614 } 615 616 @Override /* Overridden from Builder */ 617 public Builder ignoreRecursions() { 618 super.ignoreRecursions(); 619 return this; 620 } 621 622 @Override /* Overridden from Builder */ 623 public Builder ignoreRecursions(boolean value) { 624 super.ignoreRecursions(value); 625 return this; 626 } 627 628 @Override /* Overridden from Builder */ 629 public Builder ignoreUnknownBeanProperties() { 630 super.ignoreUnknownBeanProperties(); 631 return this; 632 } 633 634 @Override /* Overridden from Builder */ 635 public Builder ignoreUnknownEnumValues() { 636 super.ignoreUnknownEnumValues(); 637 return this; 638 } 639 640 @Override /* Overridden from Builder */ 641 public Builder impl(Context value) { 642 super.impl(value); 643 return this; 644 } 645 646 @Override /* Overridden from Builder */ 647 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 648 super.implClass(interfaceClass, implClass); 649 return this; 650 } 651 652 @Override /* Overridden from Builder */ 653 public Builder implClasses(Map<Class<?>,Class<?>> values) { 654 super.implClasses(values); 655 return this; 656 } 657 658 @Override /* Overridden from Builder */ 659 public Builder initialDepth(int value) { 660 super.initialDepth(value); 661 return this; 662 } 663 664 @Override /* Overridden from Builder */ 665 public Builder interfaceClass(Class<?> on, Class<?> value) { 666 super.interfaceClass(on, value); 667 return this; 668 } 669 670 @Override /* Overridden from Builder */ 671 public Builder interfaces(java.lang.Class<?>...value) { 672 super.interfaces(value); 673 return this; 674 } 675 676 /** 677 * Don't trim null bean property values. 678 * 679 * <p> 680 * When enabled, null bean values will be serialized to the output. 681 * 682 * <h5 class='section'>Notes:</h5><ul> 683 * <li class='note'>Not enabling this setting will cause <c>Map</c>s with <jk>null</jk> values to be lost during parsing. 684 * </ul> 685 * 686 * <h5 class='section'>Example:</h5> 687 * <p class='bjava'> 688 * <jc>// Create a serializer that serializes null properties.</jc> 689 * WriterSerializer <jv>serializer</jv> = JsonSerializer 690 * .<jsm>create</jsm>() 691 * .keepNullProperties() 692 * .build(); 693 * 694 * <jc>// Our bean to serialize.</jc> 695 * <jk>public class</jk> MyBean { 696 * <jk>public</jk> String <jf>foo</jf> = <jk>null</jk>; 697 * } 698 * 699 * <jc>// Will contain "{foo:null}".</jc> 700 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 701 * </p> 702 * 703 * @return This object. 704 */ 705 public Builder keepNullProperties() { 706 return keepNullProperties(true); 707 } 708 709 /** 710 * Same as {@link #keepNullProperties()} but allows you to explicitly specify the value. 711 * 712 * @param value The value for this setting. 713 * @return This object. 714 */ 715 public Builder keepNullProperties(boolean value) { 716 keepNullProperties = value; 717 return this; 718 } 719 720 /** 721 * Serializer listener. 722 * 723 * <p> 724 * Class used to listen for errors and warnings that occur during serialization. 725 * 726 * <h5 class='section'>Example:</h5> 727 * <p class='bjava'> 728 * <jc>// Define our serializer listener.</jc> 729 * <jc>// Simply captures all errors.</jc> 730 * <jk>public class</jk> MySerializerListener <jk>extends</jk> SerializerListener { 731 * 732 * <jc>// A simple property to store our events.</jc> 733 * <jk>public</jk> List<String> <jf>events</jf> = <jk>new</jk> LinkedList<>(); 734 * 735 * <ja>@Override</ja> 736 * <jk>public</jk> <T> <jk>void</jk> onError(SerializerSession <jv>session</jv>, Throwable <jv>throwable</jv>, String <jv>msg</jv>) { 737 * <jf>events</jf>.add(<jv>session</jv>.getLastLocation() + <js>","</js> + <jv>msg</jv> + <js>","</js> + <jv>throwable</jv>); 738 * } 739 * } 740 * 741 * <jc>// Create a serializer using our listener.</jc> 742 * WriterSerializer <jv>serializer</jv> = JsonSerializer 743 * .<jsm>create</jsm>() 744 * .listener(MySerializerListener.<jk>class</jk>) 745 * .build(); 746 * 747 * <jc>// Create a session object.</jc> 748 * <jc>// Needed because listeners are created per-session.</jc> 749 * <jk>try</jk> (WriterSerializerSession <jv>session</jv> = <jv>serializer</jv>.createSession()) { 750 * 751 * <jc>// Serialize a bean.</jc> 752 * String <jv>json</jv> = <jv>session</jv>.serialize(<jk>new</jk> MyBean()); 753 * 754 * <jc>// Get the listener.</jc> 755 * MySerializerListener <jv>listener</jv> = <jv>session</jv>.getListener(MySerializerListener.<jk>class</jk>); 756 * 757 * <jc>// Dump the results to the console.</jc> 758 * Json5.<jsf>DEFAULT</jsf>.println(<jv>listener</jv>.<jf>events</jf>); 759 * } 760 * </p> 761 * 762 * @param value 763 * The new value for this property. 764 * <br>Can be <jk>null</jk> (no listener will be used, listener methods will not be called). 765 * @return This object. 766 */ 767 public Builder listener(Class<? extends SerializerListener> value) { 768 listener = value; 769 return this; 770 } 771 772 @Override /* Overridden from Builder */ 773 public Builder locale(Locale value) { 774 super.locale(value); 775 return this; 776 } 777 778 @Override /* Overridden from Builder */ 779 public Builder maxDepth(int value) { 780 super.maxDepth(value); 781 return this; 782 } 783 784 @Override /* Overridden from Builder */ 785 public Builder mediaType(MediaType value) { 786 super.mediaType(value); 787 return this; 788 } 789 790 @Override /* Overridden from Builder */ 791 public Builder notBeanClasses(java.lang.Class<?>...values) { 792 super.notBeanClasses(values); 793 return this; 794 } 795 796 @Override /* Overridden from Builder */ 797 public Builder notBeanPackages(String...values) { 798 super.notBeanPackages(values); 799 return this; 800 } 801 802 /** 803 * Specifies the media type that this serializer produces. 804 * 805 * @param value The value for this setting. 806 * <br>Can be <jk>null</jk>. 807 * @return This object. 808 */ 809 public Builder produces(String value) { 810 produces = value; 811 return this; 812 } 813 814 @Override /* Overridden from Builder */ 815 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 816 super.propertyNamer(on, value); 817 return this; 818 } 819 820 @Override /* Overridden from Builder */ 821 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 822 super.propertyNamer(value); 823 return this; 824 } 825 826 /** 827 * Sort arrays and collections alphabetically. 828 * 829 * <p> 830 * When enabled, copies and sorts the contents of arrays and collections before serializing them. 831 * 832 * <p> 833 * Note that this introduces a performance penalty since it requires copying the existing collection. 834 * 835 * <h5 class='section'>Example:</h5> 836 * <p class='bjava'> 837 * <jc>// Create a serializer that sorts arrays and collections before serialization.</jc> 838 * WriterSerializer <jv>serializer</jv> = JsonSerializer 839 * .<jsm>create</jsm>() 840 * .sortCollections() 841 * .build(); 842 * 843 * <jc>// An unsorted array</jc> 844 * String[] <jv>myArray</jv> = {<js>"foo"</js>,<js>"bar"</js>,<js>"baz"</js>}; 845 * 846 * <jc>// Produces ["bar","baz","foo"]</jc> 847 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>myArray</jv>); 848 * </p> 849 * 850 * @return This object. 851 */ 852 public Builder sortCollections() { 853 return sortCollections(true); 854 } 855 856 /** 857 * Same as {@link #sortCollections()} but allows you to explicitly specify the value. 858 * 859 * @param value The value for this setting. 860 * @return This object. 861 */ 862 public Builder sortCollections(boolean value) { 863 sortCollections = value; 864 return this; 865 } 866 867 /** 868 * Sort maps alphabetically. 869 * 870 * <p> 871 * When enabled, copies and sorts the contents of maps by their keys before serializing them. 872 * 873 * <p> 874 * Note that this introduces a performance penalty. 875 * 876 * <h5 class='section'>Example:</h5> 877 * <p class='bjava'> 878 * <jc>// Create a serializer that sorts maps before serialization.</jc> 879 * WriterSerializer <jv>serializer</jv> = JsonSerializer 880 * .<jsm>create</jsm>() 881 * .sortMaps() 882 * .build(); 883 * 884 * <jc>// An unsorted map.</jc> 885 * JsonMap <jv>myMap</jv> = JsonMap.<jsm>of</jsm>(<js>"foo"</js>,1,<js>"bar"</js>,2,<js>"baz"</js>,3); 886 * 887 * <jc>// Produces {"bar":2,"baz":3,"foo":1}</jc> 888 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>myMap</jv>); 889 * </p> 890 * 891 * @return This object. 892 */ 893 public Builder sortMaps() { 894 return sortMaps(true); 895 } 896 897 /** 898 * Same as {@link #sortMaps()} but allows you to explicitly specify the value. 899 * 900 * @param value The value for this setting. 901 * @return This object. 902 */ 903 public Builder sortMaps(boolean value) { 904 sortMaps = value; 905 return this; 906 } 907 908 @Override /* Overridden from Builder */ 909 public Builder sortProperties() { 910 super.sortProperties(); 911 return this; 912 } 913 914 @Override /* Overridden from Builder */ 915 public Builder sortProperties(java.lang.Class<?>...on) { 916 super.sortProperties(on); 917 return this; 918 } 919 920 @Override /* Overridden from Builder */ 921 public Builder stopClass(Class<?> on, Class<?> value) { 922 super.stopClass(on, value); 923 return this; 924 } 925 926 @Override /* Overridden from Builder */ 927 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 928 super.swap(normalClass, swappedClass, swapFunction); 929 return this; 930 } 931 932 @Override /* Overridden from Builder */ 933 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 934 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 935 return this; 936 } 937 938 @Override /* Overridden from Builder */ 939 public Builder swaps(Class<?>...values) { 940 super.swaps(values); 941 return this; 942 } 943 944 @Override /* Overridden from Builder */ 945 public Builder swaps(Object...values) { 946 super.swaps(values); 947 return this; 948 } 949 950 @Override /* Overridden from Builder */ 951 public Builder timeZone(TimeZone value) { 952 super.timeZone(value); 953 return this; 954 } 955 956 /** 957 * Trim empty lists and arrays. 958 * 959 * <p> 960 * When enabled, empty lists and arrays will not be serialized. 961 * 962 * <p> 963 * Note that enabling this setting has the following effects on parsing: 964 * <ul class='spaced-list'> 965 * <li> 966 * Map entries with empty list values will be lost. 967 * <li> 968 * Bean properties with empty list values will not be set. 969 * </ul> 970 * 971 * <h5 class='section'>Example:</h5> 972 * <p class='bjava'> 973 * <jc>// Create a serializer that skips empty arrays and collections.</jc> 974 * WriterSerializer <jv>serializer</jv> = JsonSerializer 975 * .<jsm>create</jsm>() 976 * .trimEmptyCollections() 977 * .build(); 978 * 979 * <jc>// A bean with a field with an empty array.</jc> 980 * <jk>public class</jk> MyBean { 981 * <jk>public</jk> String[] <jf>foo</jf> = {}; 982 * } 983 * 984 * <jc>// Produces {}</jc> 985 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 986 * </p> 987 * 988 * @return This object. 989 */ 990 public Builder trimEmptyCollections() { 991 return trimEmptyCollections(true); 992 } 993 994 /** 995 * Same as {@link #trimEmptyCollections()} but allows you to explicitly specify the value. 996 * 997 * @param value The value for this setting. 998 * @return This object. 999 */ 1000 public Builder trimEmptyCollections(boolean value) { 1001 trimEmptyCollections = value; 1002 return this; 1003 } 1004 1005 /** 1006 * Trim empty maps. 1007 * 1008 * <p> 1009 * When enabled, empty map values will not be serialized to the output. 1010 * 1011 * <p> 1012 * Note that enabling this setting has the following effects on parsing: 1013 * <ul class='spaced-list'> 1014 * <li> 1015 * Bean properties with empty map values will not be set. 1016 * </ul> 1017 * 1018 * <h5 class='section'>Example:</h5> 1019 * <p class='bjava'> 1020 * <jc>// Create a serializer that skips empty maps.</jc> 1021 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1022 * .<jsm>create</jsm>() 1023 * .trimEmptyMaps() 1024 * .build(); 1025 * 1026 * <jc>// A bean with a field with an empty map.</jc> 1027 * <jk>public class</jk> MyBean { 1028 * <jk>public</jk> JsonMap <jf>foo</jf> = JsonMap.<jsm>of</jsm>(); 1029 * } 1030 * 1031 * <jc>// Produces {}</jc> 1032 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1033 * </p> 1034 * 1035 * @return This object. 1036 */ 1037 public Builder trimEmptyMaps() { 1038 return trimEmptyMaps(true); 1039 } 1040 1041 /** 1042 * Same as {@link #trimEmptyMaps()} but allows you to explicitly specify the value. 1043 * 1044 * @param value The value for this setting. 1045 * @return This object. 1046 */ 1047 public Builder trimEmptyMaps(boolean value) { 1048 trimEmptyMaps = value; 1049 return this; 1050 } 1051 1052 /** 1053 * Trim strings. 1054 * 1055 * <p> 1056 * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being serialized. 1057 * 1058 * <h5 class='section'>Example:</h5> 1059 * <p class='bjava'> 1060 * <jc>// Create a serializer that trims strings before serialization.</jc> 1061 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1062 * .<jsm>create</jsm>() 1063 * .trimStrings() 1064 * .build(); 1065 * 1066 * <jc>// A map with space-padded keys/values</jc> 1067 * JsonMap <jv>myMap</jv> = JsonMap.<jsm>of</jsm>(<js>" foo "</js>, <js>" bar "</js>); 1068 * 1069 * <jc>// Produces "{foo:'bar'}"</jc> 1070 * String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>myMap</jv>); 1071 * </p> 1072 * 1073 * @return This object. 1074 */ 1075 public Builder trimStrings() { 1076 return trimStrings(true); 1077 } 1078 1079 /** 1080 * Same as {@link #trimStrings()} but allows you to explicitly specify the value. 1081 * 1082 * @param value The value for this setting. 1083 * @return This object. 1084 */ 1085 public Builder trimStrings(boolean value) { 1086 trimStrings = value; 1087 return this; 1088 } 1089 1090 @Override /* Overridden from Builder */ 1091 public Builder type(Class<? extends org.apache.juneau.Context> value) { 1092 super.type(value); 1093 return this; 1094 } 1095 1096 @Override /* Overridden from Builder */ 1097 public Builder typeName(Class<?> on, String value) { 1098 super.typeName(on, value); 1099 return this; 1100 } 1101 1102 @Override /* Overridden from Builder */ 1103 public Builder typePropertyName(Class<?> on, String value) { 1104 super.typePropertyName(on, value); 1105 return this; 1106 } 1107 1108 @Override /* Overridden from Builder */ 1109 public Builder typePropertyName(String value) { 1110 super.typePropertyName(value); 1111 return this; 1112 } 1113 1114 /** 1115 * URI context bean. 1116 * 1117 * <p> 1118 * Bean used for resolution of URIs to absolute or root-relative form. 1119 * 1120 * <h5 class='section'>Example:</h5> 1121 * <p class='bjava'> 1122 * <jc>// Our URI contextual information.</jc> 1123 * String <jv>authority</jv> = <js>"http://localhost:10000"</js>; 1124 * String <jv>contextRoot</jv> = <js>"/myContext"</js>; 1125 * String <jv>servletPath</jv> = <js>"/myServlet"</js>; 1126 * String <jv>pathInfo</jv> = <js>"/foo"</js>; 1127 * 1128 * <jc>// Create a UriContext object.</jc> 1129 * UriContext <jv>uriContext</jv> = <jk>new</jk> UriContext(<jv>authority</jv>, <jv>contextRoot</jv>, <jv>servletPath</jv>, <jv>pathInfo</jv>); 1130 * 1131 * <jc>// Associate it with our serializer.</jc> 1132 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1133 * .<jsm>create</jsm>() 1134 * .uriContext(<jv>uriContext</jv>) 1135 * .uriRelativity(<jsf>RESOURCE</jsf>) <jc>// Assume relative paths are relative to servlet.</jc> 1136 * .uriResolution(<jsf>ABSOLUTE</jsf>) <jc>// Serialize URLs as absolute paths.</jc> 1137 * .build(); 1138 * 1139 * <jc>// A relative URL</jc> 1140 * URL <jv>myUrl</jv> = <jk>new</jk> URL(<js>"bar"</js>); 1141 * 1142 * <jc>// Produces "http://localhost:10000/myContext/myServlet/foo/bar"</jc> 1143 * String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>myUrl</jv>); 1144 * </p> 1145 * 1146 * <h5 class='section'>See Also:</h5><ul> 1147 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a> 1148 * </ul> 1149 * 1150 * @param value The new value for this property. 1151 * <br>Can be <jk>null</jk> (defaults to <c>UriContext.DEFAULT</c>). 1152 * @return This object. 1153 */ 1154 public Builder uriContext(UriContext value) { 1155 uriContext = value; 1156 return this; 1157 } 1158 1159 /** 1160 * URI relativity. 1161 * 1162 * <p> 1163 * Defines what relative URIs are relative to when serializing any of the following: 1164 * <ul> 1165 * <li>{@link java.net.URI} 1166 * <li>{@link java.net.URL} 1167 * <li>Properties and classes annotated with {@link Uri @Uri} 1168 * </ul> 1169 * 1170 * <p> 1171 * See {@link #uriContext(UriContext)} for examples. 1172 * 1173 * <ul class='values javatree'> 1174 * <li class='jf'>{@link org.apache.juneau.UriRelativity#RESOURCE} 1175 * - Relative URIs should be considered relative to the servlet URI. 1176 * <li class='jf'>{@link org.apache.juneau.UriRelativity#PATH_INFO} 1177 * - Relative URIs should be considered relative to the request URI. 1178 * </ul> 1179 * 1180 * <h5 class='section'>See Also:</h5><ul> 1181 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a> 1182 * </ul> 1183 * 1184 * @param value 1185 * The new value for this property. 1186 * <br>The default is {@link UriRelativity#RESOURCE} 1187 * <br>Can be <jk>null</jk> (defaults to <c>UriRelativity.RESOURCE</c>). 1188 * @return This object. 1189 */ 1190 public Builder uriRelativity(UriRelativity value) { 1191 uriRelativity = value; 1192 return this; 1193 } 1194 1195 /** 1196 * URI resolution. 1197 * 1198 * <p> 1199 * Defines the resolution level for URIs when serializing any of the following: 1200 * <ul> 1201 * <li>{@link java.net.URI} 1202 * <li>{@link java.net.URL} 1203 * <li>Properties and classes annotated with {@link Uri @Uri} 1204 * </ul> 1205 * 1206 * <p> 1207 * See {@link #uriContext(UriContext)} for examples. 1208 * 1209 * <ul class='values javatree'> 1210 * <li class='jf'>{@link UriResolution#ABSOLUTE} 1211 * - Resolve to an absolute URL (e.g. <js>"http://host:port/context-root/servlet-path/path-info"</js>). 1212 * <li class='jf'>{@link UriResolution#ROOT_RELATIVE} 1213 * - Resolve to a root-relative URL (e.g. <js>"/context-root/servlet-path/path-info"</js>). 1214 * <li class='jf'>{@link UriResolution#NONE} 1215 * - Don't do any URL resolution. 1216 * </ul> 1217 * 1218 * <h5 class='section'>See Also:</h5><ul> 1219 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a> 1220 * </ul> 1221 * 1222 * @param value 1223 * The new value for this property. 1224 * <br>The default is {@link UriResolution#NONE} 1225 * <br>Can be <jk>null</jk> (defaults to <c>UriResolution.NONE</c>). 1226 * @return This object. 1227 */ 1228 public Builder uriResolution(UriResolution value) { 1229 uriResolution = value; 1230 return this; 1231 } 1232 1233 @Override /* Overridden from Builder */ 1234 public Builder useEnumNames() { 1235 super.useEnumNames(); 1236 return this; 1237 } 1238 1239 @Override /* Overridden from Builder */ 1240 public Builder useJavaBeanIntrospector() { 1241 super.useJavaBeanIntrospector(); 1242 return this; 1243 } 1244 } 1245 1246 /** 1247 * Represents no Serializer. 1248 */ 1249 public static abstract class Null extends Serializer { 1250 private Null(Builder builder) { 1251 super(builder); 1252 } 1253 } 1254 1255 /** 1256 * Creates a new builder for this object. 1257 * 1258 * @return A new builder. 1259 */ 1260 public static Builder create() { 1261 return new Builder(); 1262 } 1263 1264 /** 1265 * Instantiates a builder of the specified serializer class. 1266 * 1267 * <p> 1268 * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public 1269 * or protected constructor of the class. 1270 * 1271 * @param c The builder to create. 1272 * @return A new builder. 1273 */ 1274 public static Builder createSerializerBuilder(Class<? extends Serializer> c) { 1275 return (Builder)Context.createBuilder(c); 1276 } 1277 1278 protected final boolean addBeanTypes; 1279 protected final boolean addRootType; 1280 protected final boolean keepNullProperties; 1281 protected final boolean sortCollections; 1282 protected final boolean sortMaps; 1283 protected final boolean trimEmptyCollections; 1284 protected final boolean trimEmptyMaps; 1285 protected final boolean trimStrings; 1286 protected final Class<? extends SerializerListener> listener; 1287 protected final String accept; 1288 protected final String produces; 1289 private final UriContext uriContext; 1290 private final UriRelativity uriRelativity; 1291 private final UriResolution uriResolution; 1292 private final MediaRanges acceptRanges; 1293 private final List<MediaType> acceptMediaTypes; 1294 private final MediaType producesMediaType; 1295 1296 /** 1297 * Constructor 1298 * 1299 * @param builder The builder this object. 1300 */ 1301 protected Serializer(Builder builder) { 1302 super(builder); 1303 1304 accept = builder.accept; 1305 addBeanTypes = builder.addBeanTypes; 1306 addRootType = builder.addRootType; 1307 keepNullProperties = builder.keepNullProperties; 1308 listener = builder.listener; 1309 produces = builder.produces; 1310 sortCollections = builder.sortCollections; 1311 sortMaps = builder.sortMaps; 1312 trimEmptyCollections = builder.trimEmptyCollections; 1313 trimEmptyMaps = builder.trimEmptyMaps; 1314 trimStrings = builder.trimStrings; 1315 uriContext = builder.uriContext; 1316 uriRelativity = builder.uriRelativity; 1317 uriResolution = builder.uriResolution; 1318 1319 this.producesMediaType = MediaType.of(produces); 1320 this.acceptRanges = nn(accept) ? MediaRanges.of(accept) : MediaRanges.of(produces); 1321 this.acceptMediaTypes = u(nn(builder.accept) ? l(MediaType.ofAll(splita(builder.accept))) : l(this.producesMediaType)); 1322 } 1323 1324 @Override /* Overridden from Context */ 1325 public Builder copy() { 1326 return new Builder(this); 1327 } 1328 1329 @Override /* Overridden from Context */ 1330 public SerializerSession.Builder createSession() { 1331 return SerializerSession.create(this); 1332 } 1333 1334 /** 1335 * Performs an action on the media types handled based on the value of the <c>accept</c> parameter passed into the constructor. 1336 * 1337 * <p> 1338 * The order of the media types are the same as those in the <c>accept</c> parameter. 1339 * 1340 * @param action The action to perform on the media types. 1341 * @return This object. 1342 */ 1343 public final Serializer forEachAcceptMediaType(Consumer<MediaType> action) { 1344 for (var m : acceptMediaTypes) 1345 action.accept(m); 1346 return this; 1347 } 1348 1349 /** 1350 * Returns the media types handled based on the value of the <c>accept</c> parameter passed into the constructor. 1351 * 1352 * <p> 1353 * Note that the order of these ranges are from high to low q-value. 1354 * 1355 * @return The list of media types. Never <jk>null</jk>. 1356 */ 1357 public final MediaRanges getMediaTypeRanges() { return acceptRanges; } 1358 1359 /** 1360 * Returns the first entry in the <c>accept</c> parameter passed into the constructor. 1361 * 1362 * <p> 1363 * This signifies the 'primary' media type for this serializer. 1364 * 1365 * @return The media type. Never <jk>null</jk>. 1366 */ 1367 public final MediaType getPrimaryMediaType() { return acceptMediaTypes.get(0); } 1368 1369 /** 1370 * Optional method that returns the response <c>Content-Type</c> for this serializer if it is different from 1371 * the matched media type. 1372 * 1373 * <p> 1374 * This method is specified to override the content type for this serializer. 1375 * For example, the {@link org.apache.juneau.json.Json5Serializer} class returns that it handles media type 1376 * <js>"text/json5"</js>, but returns <js>"text/json"</js> as the actual content type. 1377 * This allows clients to request specific 'flavors' of content using specialized <c>Accept</c> header values. 1378 * 1379 * <p> 1380 * This method is typically meaningless if the serializer is being used stand-alone (i.e. outside of a REST server 1381 * or client). 1382 * 1383 * @return The response content type. If <jk>null</jk>, then the matched media type is used. 1384 */ 1385 public final MediaType getResponseContentType() { return producesMediaType; } 1386 1387 /** 1388 * Optional method that specifies HTTP request headers for this serializer. 1389 * 1390 * <p> 1391 * For example, {@link SoapXmlSerializer} needs to set a <c>SOAPAction</c> header. 1392 * 1393 * <p> 1394 * This method is typically meaningless if the serializer is being used stand-alone (i.e. outside of a REST server 1395 * or client). 1396 * 1397 * @param session The current session. 1398 * @return 1399 * The HTTP headers to set on HTTP requests. 1400 * Never <jk>null</jk>. 1401 */ 1402 public Map<String,String> getResponseHeaders(SerializerSession session) { 1403 return mape(); 1404 } 1405 1406 @Override /* Overridden from Context */ 1407 public SerializerSession getSession() { return createSession().build(); } 1408 1409 /** 1410 * Returns <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}. 1411 * 1412 * @return <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}. 1413 */ 1414 public boolean isWriterSerializer() { return false; } 1415 1416 /** 1417 * Shortcut method for serializing objects directly to either a <c>String</c> or <code><jk>byte</jk>[]</code> 1418 * depending on the serializer type. 1419 * 1420 * @param o The object to serialize. 1421 * @return 1422 * The serialized object. 1423 * <br>Character-based serializers will return a <c>String</c> 1424 * <br>Stream-based serializers will return a <code><jk>byte</jk>[]</code> 1425 * @throws SerializeException If a problem occurred trying to convert the output. 1426 */ 1427 public Object serialize(Object o) throws SerializeException { 1428 return getSession().serialize(o); 1429 } 1430 1431 /** 1432 * Serializes a POJO to the specified output stream or writer. 1433 * 1434 * <p> 1435 * Equivalent to calling <c>serializer.createSession().serialize(o, output);</c> 1436 * 1437 * @param o The object to serialize. 1438 * @param output 1439 * The output object. 1440 * <br>Character-based serializers can handle the following output class types: 1441 * <ul> 1442 * <li>{@link Writer} 1443 * <li>{@link OutputStream} - Output will be written as UTF-8 encoded stream. 1444 * <li>{@link File} - Output will be written as system-default encoded stream. 1445 * <li>{@link StringBuilder} - Output will be written to the specified string builder. 1446 * </ul> 1447 * <br>Stream-based serializers can handle the following output class types: 1448 * <ul> 1449 * <li>{@link OutputStream} 1450 * <li>{@link File} 1451 * </ul> 1452 * @throws SerializeException If a problem occurred trying to convert the output. 1453 * @throws IOException Thrown by the underlying stream. 1454 */ 1455 public final void serialize(Object o, Object output) throws SerializeException, IOException { 1456 getSession().serialize(o, output); 1457 } 1458 1459 /** 1460 * Convenience method for serializing an object to a String. 1461 * 1462 * <p> 1463 * For writer-based serializers, this is identical to calling {@link #serialize(Object)}. 1464 * <br>For stream-based serializers, this converts the returned byte array to a string based on 1465 * the {@link OutputStreamSerializer.Builder#binaryFormat(BinaryFormat)} setting. 1466 * 1467 * @param o The object to serialize. 1468 * @return The output serialized to a string. 1469 * @throws SerializeException If a problem occurred trying to convert the output. 1470 */ 1471 public final String serializeToString(Object o) throws SerializeException { 1472 return getSession().serializeToString(o); 1473 } 1474 1475 /** 1476 * Serializes a POJO to the specified pipe. 1477 * 1478 * @param session The current session. 1479 * @param pipe Where to send the output from the serializer. 1480 * @param o The object to serialize. 1481 * @throws IOException Thrown by underlying stream. 1482 * @throws SerializeException Problem occurred trying to serialize object. 1483 */ 1484 protected void doSerialize(SerializerSession session, SerializerPipe pipe, Object o) throws IOException, SerializeException { 1485 throw unsupportedOp(); 1486 } 1487 1488 /** 1489 * Serializer listener. 1490 * 1491 * @see Serializer.Builder#listener(Class) 1492 * @return 1493 * Class used to listen for errors and warnings that occur during serialization. 1494 */ 1495 protected final Class<? extends SerializerListener> getListener() { return listener; } 1496 1497 /** 1498 * URI context bean. 1499 * 1500 * @see Serializer.Builder#uriContext(UriContext) 1501 * @return 1502 * Bean used for resolution of URIs to absolute or root-relative form. 1503 */ 1504 protected final UriContext getUriContext() { return uriContext; } 1505 1506 /** 1507 * URI relativity. 1508 * 1509 * @see Serializer.Builder#uriRelativity(UriRelativity) 1510 * @return 1511 * Defines what relative URIs are relative to when serializing any of the following: 1512 */ 1513 protected final UriRelativity getUriRelativity() { return uriRelativity; } 1514 1515 /** 1516 * URI resolution. 1517 * 1518 * @see Serializer.Builder#uriResolution(UriResolution) 1519 * @return 1520 * Defines the resolution level for URIs when serializing URIs. 1521 */ 1522 protected final UriResolution getUriResolution() { return uriResolution; } 1523 1524 /** 1525 * Add <js>"_type"</js> properties when needed. 1526 * 1527 * @see Serializer.Builder#addBeanTypes() 1528 * @return 1529 * <jk>true</jk> if <js>"_type"</js> properties added to beans if their type cannot be inferred 1530 * through reflection. 1531 */ 1532 protected boolean isAddBeanTypes() { return addBeanTypes; } 1533 1534 /** 1535 * Add type attribute to root nodes. 1536 * 1537 * @see Serializer.Builder#addRootType() 1538 * @return 1539 * <jk>true</jk> if type property should be added to root node. 1540 */ 1541 protected final boolean isAddRootType() { return addRootType; } 1542 1543 /** 1544 * Don't trim null bean property values. 1545 * 1546 * @see Serializer.Builder#keepNullProperties() 1547 * @return 1548 * <jk>true</jk> if null bean values are serialized to the output. 1549 */ 1550 protected final boolean isKeepNullProperties() { return keepNullProperties; } 1551 1552 /** 1553 * Sort arrays and collections alphabetically. 1554 * 1555 * @see Serializer.Builder#sortCollections() 1556 * @return 1557 * <jk>true</jk> if arrays and collections are copied and sorted before serialization. 1558 */ 1559 protected final boolean isSortCollections() { return sortCollections; } 1560 1561 /** 1562 * Sort maps alphabetically. 1563 * 1564 * @see Serializer.Builder#sortMaps() 1565 * @return 1566 * <jk>true</jk> if maps are copied and sorted before serialization. 1567 */ 1568 protected final boolean isSortMaps() { return sortMaps; } 1569 1570 /** 1571 * Trim empty lists and arrays. 1572 * 1573 * @see Serializer.Builder#trimEmptyCollections() 1574 * @return 1575 * <jk>true</jk> if empty lists and arrays are not serialized to the output. 1576 */ 1577 protected final boolean isTrimEmptyCollections() { return trimEmptyCollections; } 1578 1579 /** 1580 * Trim empty maps. 1581 * 1582 * @see Serializer.Builder#trimEmptyMaps() 1583 * @return 1584 * <jk>true</jk> if empty map values are not serialized to the output. 1585 */ 1586 protected final boolean isTrimEmptyMaps() { return trimEmptyMaps; } 1587 1588 /** 1589 * Trim strings. 1590 * 1591 * @see Serializer.Builder#trimStrings() 1592 * @return 1593 * <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being serialized. 1594 */ 1595 protected final boolean isTrimStrings() { return trimStrings; } 1596 1597 @Override /* Overridden from BeanTraverseContext */ 1598 protected FluentMap<String,Object> properties() { 1599 return super.properties() 1600 .a("addBeanTypes", addBeanTypes) 1601 .a("addRootType", addRootType) 1602 .a("keepNullProperties", keepNullProperties) 1603 .a("listener", listener) 1604 .a("sortCollections", sortCollections) 1605 .a("sortMaps", sortMaps) 1606 .a("trimEmptyCollections", trimEmptyCollections) 1607 .a("trimEmptyMaps", trimEmptyMaps) 1608 .a("trimStrings", trimStrings) 1609 .a("uriContext", uriContext) 1610 .a("uriRelativity", uriRelativity) 1611 .a("uriResolution", uriResolution); 1612 } 1613}