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