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