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; 014 015import static org.apache.juneau.Visibility.*; 016import static org.apache.juneau.collections.JsonMap.*; 017import static org.apache.juneau.common.internal.StringUtils.*; 018import static org.apache.juneau.common.internal.ThrowableUtils.*; 019import static org.apache.juneau.internal.ClassUtils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021 022import java.beans.*; 023import java.io.*; 024import java.lang.annotation.*; 025import java.lang.reflect.*; 026import java.util.*; 027import java.util.concurrent.*; 028import java.util.stream.*; 029 030import org.apache.juneau.annotation.*; 031import org.apache.juneau.collections.*; 032import org.apache.juneau.cp.*; 033import org.apache.juneau.internal.*; 034import org.apache.juneau.json.*; 035import org.apache.juneau.marshaller.*; 036import org.apache.juneau.reflect.*; 037import org.apache.juneau.serializer.*; 038import org.apache.juneau.swap.*; 039import org.apache.juneau.utils.*; 040 041/** 042 * Bean context. 043 * 044 * <p> 045 * This class servers multiple purposes: 046 * <ul class='spaced-list'> 047 * <li> 048 * Provides the ability to wrap beans inside {@link Map} interfaces. 049 * <li> 050 * Serves as a repository for metadata on POJOs, such as associated {@link Bean @Bean} annotations, 051 * {@link PropertyNamer PropertyNamers}, etc... which are used to tailor how POJOs are serialized and parsed. 052 * </ul> 053 * 054 * <p> 055 * All serializers and parsers use this context so that they can handle POJOs using a common framework. 056 * 057 * <h5 class='topic'>Bean Contexts</h5> 058 * 059 * <p> 060 * Bean contexts are created through the {@link BeanContext#create() BeanContext.create()} and {@link Builder#build()} methods. 061 * <br>These context objects are read-only, reusable, and thread-safe. 062 * 063 * <p> 064 * Each bean context maintains a cache of {@link ClassMeta} objects that describe information about classes encountered. 065 * These <c>ClassMeta</c> objects are time-consuming to construct. 066 * Therefore, instances of {@link BeanContext} that share the same <js>"BeanContext.*"</js> property values share 067 * the same cache. This allows for efficient reuse of <c>ClassMeta</c> objects so that the information about 068 * classes only needs to be calculated once. 069 * Because of this, many of the properties defined on the {@link BeanContext} class cannot be overridden on the session. 070 * 071 * <h5 class='topic'>Bean Sessions</h5> 072 * 073 * <p> 074 * Whereas <c>BeanContext</c> objects are permanent, unchangeable, cached, and thread-safe, 075 * {@link BeanSession} objects are ephemeral and not thread-safe. 076 * They are meant to be used as quickly-constructed scratchpads for creating bean maps. 077 * {@link BeanMap} objects can only be created through the session. 078 * 079 * <h5 class='topic'>BeanContext configuration properties</h5> 080 * 081 * <p> 082 * <c>BeanContexts</c> have several configuration properties that can be used to tweak behavior on how beans are 083 * handled. These are denoted as the static <jsf>BEAN_*</jsf> fields on this class. 084 * 085 * <p> 086 * Some settings (e.g. {@link Builder#beansRequireDefaultConstructor()}) are used to differentiate between bean 087 * and non-bean classes. 088 * Attempting to create a bean map around one of these objects will throw a {@link BeanRuntimeException}. 089 * The purpose for this behavior is so that the serializers can identify these non-bean classes and convert them to 090 * plain strings using the {@link Object#toString()} method. 091 * 092 * <p> 093 * Some settings (e.g. {@link Builder#beanFieldVisibility(Visibility)}) are used to determine what kinds of properties are 094 * detected on beans. 095 * 096 * <p> 097 * Some settings (e.g. {@link Builder#beanMapPutReturnsOldValue()}) change the runtime behavior of bean maps. 098 * 099 * <h5 class='section'>Example:</h5> 100 * 101 * <p class='bjava'> 102 * <jc>// Construct a context from scratch.</jc> 103 * BeanContext <jv>beanContext</jv> = BeanContext 104 * .<jsm>create</jsm>() 105 * .beansRequireDefaultConstructor() 106 * .notBeanClasses(Foo.<jk>class</jk>) 107 * .build(); 108 * </p> 109 * 110 * <h5 class='topic'>Bean Maps</h5> 111 * 112 * <p> 113 * {@link BeanMap BeanMaps} are wrappers around Java beans that allow properties to be retrieved and 114 * set using the common {@link Map#put(Object,Object)} and {@link Map#get(Object)} methods. 115 * 116 * <p> 117 * Bean maps are created in two ways... 118 * <ol> 119 * <li>{@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - Wraps an existing bean inside a {@code Map} 120 * wrapper. 121 * <li>{@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - Create a new bean instance wrapped in a 122 * {@code Map} wrapper. 123 * </ol> 124 * 125 * <h5 class='section'>Example:</h5> 126 * 127 * <p class='bjava'> 128 * <jc>// A sample bean class</jc> 129 * <jk>public class</jk> Person { 130 * <jk>public</jk> String getName(); 131 * <jk>public void</jk> setName(String <jv>name</jv>); 132 * <jk>public int</jk> getAge(); 133 * <jk>public void</jk> setAge(<jk>int</jk> <jv>age</jv>); 134 * } 135 * 136 * <jc>// Create a new bean session</jc> 137 * BeanSession <jv>session</jv> = BeanContext.<jsf>DEFAULT</jsf>.createSession(); 138 * 139 * <jc>// Wrap an existing bean in a new bean map</jc> 140 * BeanMap<Person> <jv>map1</jv> = <jv>session</jv>.toBeanMap(<jk>new</jk> Person()); 141 * <jv>map1</jv>.put(<js>"name"</js>, <js>"John Smith"</js>); 142 * <jv>map1</jv>.put(<js>"age"</js>, 45); 143 * 144 * <jc>// Create a new bean instance wrapped in a new bean map</jc> 145 * BeanMap<Person> <jv>map2</jv> = <jv>session</jv>.newBeanMap(Person.<jk>class</jk>); 146 * <jv>map2</jv>.put(<js>"name"</js>, <js>"John Smith"</js>); 147 * <jv>map2</jv>.put(<js>"age"</js>, 45); 148 * Person <jv>person</jv> = <jv>map2</jv>.getBean(); <jc>// Get the bean instance that was created.</jc> 149 * </p> 150 * 151 * <h5 class='section'>Notes:</h5><ul> 152 * <li class='note'>This class is thread safe and reusable. 153 * </ul> 154 * 155 * <h5 class='section'>See Also:</h5><ul> 156 * <li class='link'><a class="doclink" href="../../../index.html#jm.BeanContexts">Bean Contexts</a> 157 * </ul> 158 */ 159@SuppressWarnings({"unchecked","rawtypes"}) 160public class BeanContext extends Context { 161 162 //----------------------------------------------------------------------------------------------------------------- 163 // Static 164 //----------------------------------------------------------------------------------------------------------------- 165 166 /* 167 * The default package pattern exclusion list. 168 * Any beans in packages in this list will not be considered beans. 169 */ 170 private static final String[] DEFAULT_NOTBEAN_PACKAGES = { 171 "java.lang", 172 "java.lang.annotation", 173 "java.lang.ref", 174 "java.lang.reflect", 175 "java.io", 176 "java.net", 177 "java.nio.*", 178 "java.util.*" 179 }; 180 181 /* 182 * The default bean class exclusion list. 183 * Anything in this list will not be considered beans. 184 */ 185 private static final Class<?>[] DEFAULT_NOTBEAN_CLASSES = { 186 Map.class, 187 Collection.class, 188 Reader.class, 189 Writer.class, 190 InputStream.class, 191 OutputStream.class, 192 Throwable.class 193 }; 194 195 196 /** Default config. All default settings. */ 197 public static final BeanContext DEFAULT = create().build(); 198 199 /** Default config. All default settings except sort bean properties. */ 200 public static final BeanContext DEFAULT_SORTED = create().sortProperties().build(); 201 202 /** Default reusable unmodifiable session. Can be used to avoid overhead of creating a session (for creating BeanMaps for example).*/ 203 public static final BeanSession DEFAULT_SESSION = DEFAULT.createSession().unmodifiable().build(); 204 205 /** 206 * Creates a new builder for this object. 207 * 208 * @return A new builder. 209 */ 210 public static Builder create() { 211 return new Builder(); 212 } 213 214 //----------------------------------------------------------------------------------------------------------------- 215 // Builder 216 //----------------------------------------------------------------------------------------------------------------- 217 218 /** 219 * Builder class. 220 */ 221 @FluentSetters 222 public static class Builder extends Context.Builder { 223 224 private static final Cache<HashKey,BeanContext> CACHE = Cache.of(HashKey.class, BeanContext.class).build(); 225 226 Visibility beanClassVisibility, beanConstructorVisibility, beanMethodVisibility, beanFieldVisibility; 227 boolean disableBeansRequireSomeProperties, beanMapPutReturnsOldValue, beansRequireDefaultConstructor, beansRequireSerializable, 228 beansRequireSettersForGetters, disableIgnoreTransientFields, disableIgnoreUnknownNullBeanProperties, disableIgnoreMissingSetters, 229 disableInterfaceProxies, findFluentSetters, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters, 230 ignoreUnknownBeanProperties, ignoreUnknownEnumValues, sortProperties, useEnumNames, useJavaBeanIntrospector; 231 String typePropertyName; 232 MediaType mediaType; 233 Locale locale; 234 TimeZone timeZone; 235 Class<? extends PropertyNamer> propertyNamer; 236 List<Class<?>> beanDictionary; 237 List<Object> swaps; 238 Set<Class<?>> notBeanClasses; 239 Set<String> notBeanPackages; 240 241 /** 242 * Constructor. 243 * 244 * All default settings. 245 */ 246 protected Builder() { 247 super(); 248 beanClassVisibility = env("BeanContext.beanClassVisibility", PUBLIC); 249 beanConstructorVisibility = env("BeanContext.beanConstructorVisibility", PUBLIC); 250 beanMethodVisibility = env("BeanContext.beanMethodVisibility", PUBLIC); 251 beanFieldVisibility = env("BeanContext.beanFieldVisibility", PUBLIC); 252 beanDictionary = null; 253 swaps = null; 254 notBeanClasses = null; 255 notBeanPackages = null; 256 disableBeansRequireSomeProperties = env("BeanContext.disableBeansRequireSomeProperties", false); 257 beanMapPutReturnsOldValue = env("BeanContext.beanMapPutReturnsOldValue", false); 258 beansRequireDefaultConstructor = env("BeanContext.beansRequireDefaultConstructor", false); 259 beansRequireSerializable = env("BeanContext.beansRequireSerializable", false); 260 beansRequireSettersForGetters = env("BeanContext.beansRequireSettersForGetters", false); 261 disableIgnoreTransientFields = env("BeanContext.disableIgnoreTransientFields", false); 262 disableIgnoreUnknownNullBeanProperties = env("BeanContext.disableIgnoreUnknownNullBeanProperties", false); 263 disableIgnoreMissingSetters = env("BeanContext.disableIgnoreMissingSetters", false); 264 disableInterfaceProxies = env("BeanContext.disableInterfaceProxies", false); 265 findFluentSetters = env("BeanContext.findFluentSetters", false); 266 ignoreInvocationExceptionsOnGetters = env("BeanContext.ignoreInvocationExceptionsOnGetters", false); 267 ignoreInvocationExceptionsOnSetters = env("BeanContext.ignoreInvocationExceptionsOnSetters", false); 268 ignoreUnknownBeanProperties = env("BeanContext.ignoreUnknownBeanProperties", false); 269 ignoreUnknownEnumValues = env("BeanContext.ignoreUnknownEnumValues", false); 270 sortProperties = env("BeanContext.sortProperties", false); 271 useEnumNames = env("BeanContext.useEnumNames", false); 272 useJavaBeanIntrospector = env("BeanContext.useJavaBeanIntrospector", false); 273 typePropertyName = env("BeanContext.typePropertyName", "_type"); 274 mediaType = env("BeanContext.mediaType", (MediaType)null); 275 timeZone = env("BeanContext.timeZone", (TimeZone)null); 276 locale = env("BeanContext.locale", Locale.getDefault()); 277 propertyNamer = null; 278 } 279 280 /** 281 * Copy constructor. 282 * 283 * @param copyFrom The bean to copy from. 284 */ 285 protected Builder(BeanContext copyFrom) { 286 super(copyFrom); 287 beanClassVisibility = copyFrom.beanClassVisibility; 288 beanConstructorVisibility = copyFrom.beanConstructorVisibility; 289 beanMethodVisibility = copyFrom.beanMethodVisibility; 290 beanFieldVisibility = copyFrom.beanFieldVisibility; 291 beanDictionary = listFrom(copyFrom.beanDictionary, true); 292 swaps = listFrom(copyFrom.swaps, true); 293 notBeanClasses = classSet(copyFrom.notBeanClasses, true); 294 notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages, true); 295 disableBeansRequireSomeProperties = ! copyFrom.beansRequireSomeProperties; 296 beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; 297 beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; 298 beansRequireSerializable = copyFrom.beansRequireSerializable; 299 beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; 300 disableIgnoreTransientFields = ! copyFrom.ignoreTransientFields; 301 disableIgnoreUnknownNullBeanProperties = ! copyFrom.ignoreUnknownNullBeanProperties; 302 disableIgnoreMissingSetters = ! copyFrom.ignoreMissingSetters; 303 disableInterfaceProxies = ! copyFrom.useInterfaceProxies; 304 findFluentSetters = copyFrom.findFluentSetters; 305 ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; 306 ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; 307 ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; 308 ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; 309 sortProperties = copyFrom.sortProperties; 310 useEnumNames = copyFrom.useEnumNames; 311 useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; 312 typePropertyName = copyFrom.typePropertyName; 313 mediaType = copyFrom.mediaType; 314 timeZone = copyFrom.timeZone; 315 locale = copyFrom.locale; 316 propertyNamer = copyFrom.propertyNamer; 317 } 318 319 /** 320 * Copy constructor. 321 * 322 * @param copyFrom The builder to copy from. 323 */ 324 protected Builder(Builder copyFrom) { 325 super(copyFrom); 326 beanClassVisibility = copyFrom.beanClassVisibility; 327 beanConstructorVisibility = copyFrom.beanConstructorVisibility; 328 beanMethodVisibility = copyFrom.beanMethodVisibility; 329 beanFieldVisibility = copyFrom.beanFieldVisibility; 330 beanDictionary = copyOf(copyFrom.beanDictionary); 331 swaps = copyOf(copyFrom.swaps); 332 notBeanClasses = classSet(copyFrom.notBeanClasses); 333 notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages); 334 disableBeansRequireSomeProperties = copyFrom.disableBeansRequireSomeProperties; 335 beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; 336 beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; 337 beansRequireSerializable = copyFrom.beansRequireSerializable; 338 beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; 339 disableIgnoreTransientFields = copyFrom.disableIgnoreTransientFields; 340 disableIgnoreUnknownNullBeanProperties = copyFrom.disableIgnoreUnknownNullBeanProperties; 341 disableIgnoreMissingSetters = copyFrom.disableIgnoreMissingSetters; 342 disableInterfaceProxies = copyFrom.disableInterfaceProxies; 343 findFluentSetters = copyFrom.findFluentSetters; 344 ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; 345 ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; 346 ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; 347 ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; 348 sortProperties = copyFrom.sortProperties; 349 useEnumNames = copyFrom.useEnumNames; 350 useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; 351 typePropertyName = copyFrom.typePropertyName; 352 mediaType = copyFrom.mediaType; 353 timeZone = copyFrom.timeZone; 354 locale = copyFrom.locale; 355 propertyNamer = copyFrom.propertyNamer; 356 } 357 358 @Override /* Context.Builder */ 359 public Builder copy() { 360 return new Builder(this); 361 } 362 363 @Override /* Context.Builder */ 364 public BeanContext build() { 365 return cache(CACHE).build(BeanContext.class); 366 } 367 368 @Override /* Context.Builder */ 369 public HashKey hashKey() { 370 return HashKey.of( 371 super.hashKey(), 372 beanClassVisibility, 373 beanConstructorVisibility, 374 beanMethodVisibility, 375 beanFieldVisibility, 376 beanDictionary, 377 swaps, 378 notBeanClasses, 379 notBeanPackages, 380 integer( 381 disableBeansRequireSomeProperties, 382 beanMapPutReturnsOldValue, 383 beansRequireDefaultConstructor, 384 beansRequireSerializable, 385 beansRequireSettersForGetters, 386 disableIgnoreTransientFields, 387 disableIgnoreUnknownNullBeanProperties, 388 disableIgnoreMissingSetters, 389 disableInterfaceProxies, 390 findFluentSetters, 391 ignoreInvocationExceptionsOnGetters, 392 ignoreInvocationExceptionsOnSetters, 393 ignoreUnknownBeanProperties, 394 ignoreUnknownEnumValues, 395 sortProperties, 396 useEnumNames, 397 useJavaBeanIntrospector 398 ), 399 typePropertyName, 400 mediaType, 401 timeZone, 402 locale, 403 propertyNamer 404 ); 405 } 406 407 private int integer(boolean...values) { 408 int n = 0; 409 for (boolean b : values) 410 n = (n << 1) | (b ? 1 : 0); 411 return n; 412 } 413 414 //----------------------------------------------------------------------------------------------------------------- 415 // Properties 416 //----------------------------------------------------------------------------------------------------------------- 417 418 /** 419 * Minimum bean class visibility. 420 * 421 * <p> 422 * Classes are not considered beans unless they meet the minimum visibility requirements. 423 * For example, if the visibility is <jsf>PUBLIC</jsf> and the bean class is <jk>protected</jk>, then the class 424 * will not be interpreted as a bean class and be serialized as a string. 425 * Use this setting to reduce the visibility requirement. 426 * 427 * <h5 class='section'>Example:</h5> 428 * <p class='bjava'> 429 * <jc>// A bean with a protected class and one field.</jc> 430 * <jk>protected class</jk> MyBean { 431 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 432 * } 433 * 434 * <jc>// Create a serializer that's capable of serializing the class.</jc> 435 * WriterSerializer <jv>serializer</jv> = JsonSerializer 436 * .<jsm>create</jsm>() 437 * .beanClassVisibility(<jsf>PROTECTED</jsf>) 438 * .build(); 439 * 440 * <jc>// Produces: {"foo","bar"}</jc> 441 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 442 * </p> 443 * 444 * <h5 class='section'>Notes:</h5><ul> 445 * <li class='note'>The {@link Bean @Bean} annotation can be used on a non-public bean class to override this setting. 446 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean class to ignore it as a bean. 447 * </ul> 448 * 449 * <h5 class='section'>See Also:</h5><ul> 450 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanClassVisibility()} 451 * </ul> 452 * 453 * @param value 454 * The new value for this setting. 455 * <br>The default is {@link Visibility#PUBLIC}. 456 * @return This object. 457 */ 458 @FluentSetter 459 public Builder beanClassVisibility(Visibility value) { 460 beanClassVisibility = value; 461 return this; 462 } 463 464 /** 465 * Minimum bean constructor visibility. 466 * 467 * <p> 468 * Only look for constructors with the specified minimum visibility. 469 * 470 * <p> 471 * This setting affects the logic for finding no-arg constructors for bean. Normally, only <jk>public</jk> no-arg 472 * constructors are used. Use this setting if you want to reduce the visibility requirement. 473 * 474 * <h5 class='section'>Example:</h5> 475 * <p class='bjava'> 476 * <jc>// A bean with a protected constructor and one field.</jc> 477 * <jk>public class</jk> MyBean { 478 * <jk>public</jk> String <jf>foo</jf>; 479 * 480 * <jk>protected</jk> MyBean() {} 481 * } 482 * 483 * <jc>// Create a parser capable of calling the protected constructor.</jc> 484 * ReaderParser <jv>parser</jv> = ReaderParser 485 * .<jsm>create</jsm>() 486 * .beanConstructorVisibility(<jsf>PROTECTED</jsf>) 487 * .build(); 488 * 489 * <jc>// Use it.</jc> 490 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 491 * </p> 492 * 493 * <h5 class='section'>Notes:</h5><ul> 494 * <li class='note'>The {@link Beanc @Beanc} annotation can also be used to expose a non-public constructor. 495 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean constructor to ignore it. 496 * </ul> 497 * 498 * <h5 class='section'>See Also:</h5><ul> 499 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanConstructorVisibility()} 500 * </ul> 501 * 502 * @param value 503 * The new value for this setting. 504 * <br>The default is {@link Visibility#PUBLIC}. 505 * @return This object. 506 */ 507 @FluentSetter 508 public Builder beanConstructorVisibility(Visibility value) { 509 beanConstructorVisibility = value; 510 return this; 511 } 512 513 /** 514 * Minimum bean field visibility. 515 * 516 * <p> 517 * Only look for bean fields with the specified minimum visibility. 518 * 519 * <p> 520 * This affects which fields on a bean class are considered bean properties. Normally only <jk>public</jk> fields are considered. 521 * Use this setting if you want to reduce the visibility requirement. 522 * 523 * <h5 class='section'>Example:</h5> 524 * <p class='bjava'> 525 * <jc>// A bean with a protected field.</jc> 526 * <jk>public class</jk> MyBean { 527 * <jk>protected</jk> String <jf>foo</jf> = <js>"bar"</js>; 528 * } 529 * 530 * <jc>// Create a serializer that recognizes the protected field.</jc> 531 * WriterSerializer <jv>serializer</jv> = JsonSerializer 532 * .<jsm>create</jsm>() 533 * .beanFieldVisibility(<jsf>PROTECTED</jsf>) 534 * .build(); 535 * 536 * <jc>// Produces: {"foo":"bar"}</jc> 537 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 538 * </p> 539 * 540 * <p> 541 * Bean fields can be ignored as properties entirely by setting the value to {@link Visibility#NONE} 542 * 543 * <p class='bjava'> 544 * <jc>// Disable using fields as properties entirely.</jc> 545 * WriterSerializer <jv>serializer</jv> = JsonSerializer 546 * .<jsm>create</jsm>() 547 * .beanFieldVisibility(<jsf>NONE</jsf>) 548 * .build(); 549 * </p> 550 * 551 * <h5 class='section'>Notes:</h5><ul> 552 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public field. 553 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean field to ignore it as a bean property. 554 * </ul> 555 * 556 * <h5 class='section'>See Also:</h5><ul> 557 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanFieldVisibility()} 558 * </ul> 559 * 560 * @param value 561 * The new value for this setting. 562 * <br>The default is {@link Visibility#PUBLIC}. 563 * @return This object. 564 */ 565 @FluentSetter 566 public Builder beanFieldVisibility(Visibility value) { 567 beanFieldVisibility = value; 568 return this; 569 } 570 571 /** 572 * Bean interceptor. 573 * 574 * <p> 575 * Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit. 576 * 577 * <h5 class='section'>Example:</h5> 578 * <p class='bjava'> 579 * <jc>// Interceptor that strips out sensitive information.</jc> 580 * <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor<Address> { 581 * 582 * <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 583 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>)) 584 * <jk>return</jk> <js>"redacted"</js>; 585 * <jk>return</jk> <jv>value</jv>; 586 * } 587 * 588 * <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 589 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) && <js>"redacted"</js>.equals(<jv>value</jv>)) 590 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState()); 591 * <jk>return</jk> <jv>value</jv>; 592 * } 593 * } 594 * 595 * <jc>// Our bean class.</jc> 596 * <jk>public class</jk> Address { 597 * <jk>public</jk> String getTaxInfo() {...} 598 * <jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...} 599 * } 600 * 601 * <jc>// Register filter on serializer or parser.</jc> 602 * WriterSerializer <jv>serializer</jv> = JsonSerializer 603 * .<jsm>create</jsm>() 604 * .beanInterceptor(Address.<jk>class</jk>, AddressInterceptor.<jk>class</jk>) 605 * .build(); 606 * 607 * <jc>// Produces: {"taxInfo":"redacted"}</jc> 608 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Address()); 609 * </p> 610 * 611 * <h5 class='section'>See Also:</h5><ul> 612 * <li class='jc'>{@link BeanInterceptor} 613 * <li class='ja'>{@link Bean#interceptor() Bean(interceptor)} 614 * </ul> 615 * 616 * @param on The bean that the filter applies to. 617 * @param value 618 * The new value for this setting. 619 * @return This object. 620 */ 621 @FluentSetter 622 public Builder beanInterceptor(Class<?> on, Class<? extends BeanInterceptor<?>> value) { 623 return annotations(BeanAnnotation.create(on).interceptor(value).build()); 624 } 625 626 /** 627 * BeanMap.put() returns old property value. 628 * 629 * <p> 630 * When enabled, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property 631 * values. Otherwise, it returns <jk>null</jk>. 632 * 633 * <p> 634 * Disabled by default because it introduces a slight performance penalty during serialization. 635 * 636 * <h5 class='section'>Example:</h5> 637 * <p class='bjava'> 638 * <jc>// Create a context that creates BeanMaps with normal put() behavior.</jc> 639 * BeanContext <jv>context</jv> = BeanContext 640 * .<jsm>create</jsm>() 641 * .beanMapPutReturnsOldValue() 642 * .build(); 643 * 644 * BeanMap<MyBean> <jv>myBeanMap</jv> = <jv>context</jv>.createSession().toBeanMap(<jk>new</jk> MyBean()); 645 * <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"bar"</js>); 646 * Object <jv>oldValue</jv> = <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"baz"</js>); <jc>// oldValue == "bar"</jc> 647 * </p> 648 * 649 * <h5 class='section'>See Also:</h5><ul> 650 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMapPutReturnsOldValue()} 651 * </ul> 652 * 653 * @return This object. 654 */ 655 @FluentSetter 656 public Builder beanMapPutReturnsOldValue() { 657 return beanMapPutReturnsOldValue(true); 658 } 659 660 /** 661 * Same as {@link #beanMapPutReturnsOldValue()} but allows you to explicitly specify the value. 662 * 663 * @param value The value for this setting. 664 * @return This object. 665 */ 666 @FluentSetter 667 public Builder beanMapPutReturnsOldValue(boolean value) { 668 beanMapPutReturnsOldValue = value; 669 return this; 670 } 671 672 /** 673 * Minimum bean method visibility. 674 * 675 * <p> 676 * Only look for bean methods with the specified minimum visibility. 677 * 678 * <p> 679 * This affects which methods are detected as getters and setters on a bean class. Normally only <jk>public</jk> getters and setters are considered. 680 * Use this setting if you want to reduce the visibility requirement. 681 * 682 * <h5 class='section'>Example:</h5> 683 * <p class='bjava'> 684 * <jc>// A bean with a protected getter.</jc> 685 * <jk>public class</jk> MyBean { 686 * <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; } 687 * <jk>protected</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; } 688 * } 689 * 690 * <jc>// Create a serializer that looks for protected getters and setters.</jc> 691 * WriterSerializer <jv>serializer</jv> = JsonSerializer 692 * .<jsm>create</jsm>() 693 * .beanMethodVisibility(<jsf>PROTECTED</jsf>) 694 * .build(); 695 * 696 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 697 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 698 * </p> 699 * 700 * <h5 class='section'>Notes:</h5><ul> 701 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public method. 702 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean getter/setter to ignore it as a bean property. 703 * </ul> 704 * 705 * <h5 class='section'>See Also:</h5><ul> 706 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMethodVisibility()} 707 * </ul> 708 * 709 * @param value 710 * The new value for this setting. 711 * <br>The default is {@link Visibility#PUBLIC} 712 * @return This object. 713 */ 714 @FluentSetter 715 public Builder beanMethodVisibility(Visibility value) { 716 beanMethodVisibility = value; 717 return this; 718 } 719 720 /** 721 * Beans require no-arg constructors. 722 * 723 * <p> 724 * When enabled, a Java class must implement a default no-arg constructor to be considered a bean. 725 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 726 * 727 * <h5 class='section'>Example:</h5> 728 * <p class='bjava'> 729 * <jc>// A bean without a no-arg constructor.</jc> 730 * <jk>public class</jk> MyBean { 731 * 732 * <jc>// A property method.</jc> 733 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 734 * 735 * <jc>// A no-arg constructor</jc> 736 * <jk>public</jk> MyBean(String <jv>foo</jv>) { 737 * <jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>; 738 * } 739 * 740 * <ja>@Override</ja> 741 * <jk>public</jk> String toString() { 742 * <jk>return</jk> <js>"bar"</js>; 743 * } 744 * } 745 * 746 * <jc>// Create a serializer that ignores beans without default constructors.</jc> 747 * WriterSerializer <jv>serializer</jv> = JsonSerializer 748 * .<jsm>create</jsm>() 749 * .beansRequireDefaultConstructor() 750 * .build(); 751 * 752 * <jc>// Produces: "bar"</jc> 753 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 754 * </p> 755 * 756 * <h5 class='section'>Notes:</h5><ul> 757 * <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting. 758 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. 759 * </ul> 760 * 761 * <h5 class='section'>See Also:</h5><ul> 762 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireDefaultConstructor()} 763 * </ul> 764 * 765 * @return This object. 766 */ 767 @FluentSetter 768 public Builder beansRequireDefaultConstructor() { 769 return beansRequireDefaultConstructor(true); 770 } 771 772 /** 773 * Same as {@link #beansRequireDefaultConstructor()} but allows you to explicitly specify the value. 774 * 775 * @param value The value for this setting. 776 * @return This object. 777 */ 778 @FluentSetter 779 public Builder beansRequireDefaultConstructor(boolean value) { 780 beansRequireDefaultConstructor = value; 781 return this; 782 } 783 784 /** 785 * Beans require Serializable interface. 786 * 787 * <p> 788 * When enabled, a Java class must implement the {@link Serializable} interface to be considered a bean. 789 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 790 * 791 * <h5 class='section'>Example:</h5> 792 * <p class='bjava'> 793 * <jc>// A bean without a Serializable interface.</jc> 794 * <jk>public class</jk> MyBean { 795 * 796 * <jc>// A property method.</jc> 797 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 798 * 799 * <ja>@Override</ja> 800 * <jk>public</jk> String toString() { 801 * <jk>return</jk> <js>"bar"</js>; 802 * } 803 * } 804 * 805 * <jc>// Create a serializer that ignores beans not implementing Serializable.</jc> 806 * WriterSerializer <jv>serializer</jv> = JsonSerializer 807 * .<jsm>create</jsm>() 808 * .beansRequireSerializable() 809 * .build(); 810 * 811 * <jc>// Produces: "bar"</jc> 812 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 813 * </p> 814 * 815 * <h5 class='section'>Notes:</h5><ul> 816 * <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting. 817 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. 818 * </ul> 819 * 820 * <h5 class='section'>See Also:</h5><ul> 821 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireSerializable()} 822 * </ul> 823 * 824 * @return This object. 825 */ 826 @FluentSetter 827 public Builder beansRequireSerializable() { 828 return beansRequireSerializable(true); 829 } 830 831 /** 832 * Same as {@link #beansRequireSerializable()} but allows you to explicitly specify the value. 833 * 834 * @param value The value for this setting. 835 * @return This object. 836 */ 837 @FluentSetter 838 public Builder beansRequireSerializable(boolean value) { 839 beansRequireSerializable = value; 840 return this; 841 } 842 843 /** 844 * Beans require setters for getters. 845 * 846 * <p> 847 * When enabled, ignore read-only properties (properties with getters but not setters). 848 * 849 * <h5 class='section'>Example:</h5> 850 * <p class='bjava'> 851 * <jc>// A bean without a Serializable interface.</jc> 852 * <jk>public class</jk> MyBean { 853 * 854 * <jc>// A read/write property.</jc> 855 * <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; } 856 * <jk>public void</jk> setFoo(String <jv>foo</jv>) { ... } 857 * 858 * <jc>// A read-only property.</jc> 859 * <jk>public</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; } 860 * } 861 * 862 * <jc>// Create a serializer that ignores bean properties without setters.</jc> 863 * WriterSerializer <jv>serializer</jv> = JsonSerializer 864 * .<jsm>create</jsm>() 865 * .beansRequireSettersForGetters() 866 * .build(); 867 * 868 * <jc>// Produces: {"foo":"foo"}</jc> 869 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 870 * </p> 871 * 872 * <h5 class='section'>Notes:</h5><ul> 873 * <li class='note'>The {@link Beanp @Beanp} annotation can be used on the getter to override this setting. 874 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters to ignore them as bean properties. 875 * </ul> 876 * 877 * @return This object. 878 */ 879 @FluentSetter 880 public Builder beansRequireSettersForGetters() { 881 return beansRequireSettersForGetters(true); 882 } 883 884 /** 885 * Same as {@link #beansRequireSettersForGetters()} but allows you to explicitly specify the value. 886 * 887 * @param value The value for this setting. 888 * @return This object. 889 */ 890 @FluentSetter 891 public Builder beansRequireSettersForGetters(boolean value) { 892 beansRequireSettersForGetters = value; 893 return this; 894 } 895 896 /** 897 * Beans don't require at least one property. 898 * 899 * <p> 900 * When enabled, then a Java class doesn't need to contain at least 1 property to be considered a bean. 901 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 902 * 903 * <p> 904 * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>. 905 * 906 * <h5 class='section'>Example:</h5> 907 * <p class='bjava'> 908 * <jc>// A bean with no properties.</jc> 909 * <jk>public class</jk> MyBean { 910 * } 911 * 912 * <jc>// Create a serializer that serializes beans even if they have zero properties.</jc> 913 * WriterSerializer <jv>serializer</jv> = JsonSerializer 914 * .<jsm>create</jsm>() 915 * .disableBeansRequireSomeProperties() 916 * .build(); 917 * 918 * <jc>// Produces: {}</jc> 919 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 920 * </p> 921 * 922 * <h5 class='section'>Notes:</h5><ul> 923 * <li class='note'>The {@link Bean @Bean} annotation can be used on the class to force it to be recognized as a bean class 924 * even if it has no properties. 925 * </ul> 926 * 927 * <h5 class='section'>See Also:</h5><ul> 928 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableBeansRequireSomeProperties()} 929 * </ul> 930 * 931 * @return This object. 932 */ 933 @FluentSetter 934 public Builder disableBeansRequireSomeProperties() { 935 return disableBeansRequireSomeProperties(true); 936 } 937 938 /** 939 * Same as {@link #disableBeansRequireSomeProperties()} but allows you to explicitly specify the value. 940 * 941 * @param value The value for this setting. 942 * @return This object. 943 */ 944 @FluentSetter 945 public Builder disableBeansRequireSomeProperties(boolean value) { 946 disableBeansRequireSomeProperties = value; 947 return this; 948 } 949 950 /** 951 * Bean property includes. 952 * 953 * <p> 954 * Specifies the set and order of names of properties associated with the bean class. 955 * 956 * <p> 957 * For example, <c>beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and 958 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 959 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 960 * has been called. 961 * 962 * <p> 963 * This value is entirely optional if you simply want to expose all the getters and public fields on 964 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 965 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 966 * whereas on Oracle JREs, the order is entirely random. 967 * 968 * <p> 969 * Setting applies to specified class and all subclasses. 970 * 971 * <h5 class='section'>Example:</h5> 972 * <p class='bjava'> 973 * <jc>// A bean with 3 properties.</jc> 974 * <jk>public class</jk> MyBean { 975 * <jk>public</jk> String 976 * <jf>foo</jf> = <js>"foo"</js>, 977 * <jf>bar</jf> = <js>"bar"</js>, 978 * <jf>baz</jf> = <js>"baz"</js>; 979 * } 980 * 981 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 982 * WriterSerializer <jv>serializer</jv> = JsonSerializer 983 * .<jsm>create</jsm>() 984 * .beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 985 * .build(); 986 * 987 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 988 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 989 * </p> 990 * 991 * <p> 992 * This method is functionally equivalent to the following code: 993 * <p class='bjava'> 994 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).properties(<jv>properties</jv>).build()); 995 * </p> 996 * 997 * <h5 class='section'>See Also:</h5><ul> 998 * <li class='jma'>{@link Bean#properties()}/{@link Bean#p()} - On an annotation on the bean class itself. 999 * </ul> 1000 * 1001 * @param beanClass The bean class. 1002 * @param properties Comma-delimited list of property names. 1003 * @return This object. 1004 */ 1005 @FluentSetter 1006 public Builder beanProperties(Class<?> beanClass, String properties) { 1007 return annotations(BeanAnnotation.create(beanClass).p(properties).build()); 1008 } 1009 1010 /** 1011 * Bean property includes. 1012 * 1013 * <p> 1014 * Specifies the set and order of names of properties associated with bean classes. 1015 * 1016 * <p> 1017 * For example, <c>beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))</c> means only serialize the <c>foo</c> and 1018 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 1019 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 1020 * has been called. 1021 * 1022 * <p> 1023 * This value is entirely optional if you simply want to expose all the getters and public fields on 1024 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 1025 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 1026 * whereas on Oracle JREs, the order is entirely random. 1027 * 1028 * <p> 1029 * Setting applies to specified class and all subclasses. 1030 * 1031 * <h5 class='section'>Example:</h5> 1032 * <p class='bjava'> 1033 * <jc>// A bean with 3 properties.</jc> 1034 * <jk>public class</jk> MyBean { 1035 * <jk>public</jk> String 1036 * <jf>foo</jf> = <js>"foo"</js>, 1037 * <jf>bar</jf> = <js>"bar"</js>, 1038 * <jf>baz</jf> = <js>"baz"</js>; 1039 * } 1040 * 1041 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 1042 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1043 * .<jsm>create</jsm>() 1044 * .beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>)) 1045 * .build(); 1046 * 1047 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 1048 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1049 * </p> 1050 * 1051 * <p> 1052 * This method is functionally equivalent to the following code for each entry: 1053 * <p class='bjava'> 1054 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).properties(<jv>value</jv>.toString()).build()); 1055 * </p> 1056 * 1057 * <h5 class='section'>See Also:</h5><ul> 1058 * <li class='jma'>{@link Bean#properties()} / {@link Bean#p()}- On an annotation on the bean class itself. 1059 * </ul> 1060 * 1061 * @param values 1062 * The values to add to this builder. 1063 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1064 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1065 * @return This object. 1066 */ 1067 @FluentSetter 1068 public Builder beanProperties(Map<String,Object> values) { 1069 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).p(stringify(v)).build())); 1070 return this; 1071 } 1072 1073 /** 1074 * Bean property includes. 1075 * 1076 * <p> 1077 * Specifies the set and order of names of properties associated with the bean class. 1078 * 1079 * <p> 1080 * For example, <c>beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and 1081 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 1082 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 1083 * has been called. 1084 * 1085 * <p> 1086 * This value is entirely optional if you simply want to expose all the getters and public fields on 1087 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 1088 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 1089 * whereas on Oracle JREs, the order is entirely random. 1090 * 1091 * <p> 1092 * Setting applies to specified class and all subclasses. 1093 * 1094 * <h5 class='section'>Example:</h5> 1095 * <p class='bjava'> 1096 * <jc>// A bean with 3 properties.</jc> 1097 * <jk>public class</jk> MyBean { 1098 * <jk>public</jk> String 1099 * <jf>foo</jf> = <js>"foo"</js>, 1100 * <jf>bar</jf> = <js>"bar"</js>, 1101 * <jf>baz</jf> = <js>"baz"</js>; 1102 * } 1103 * 1104 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 1105 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1106 * .<jsm>create</jsm>() 1107 * .beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>) 1108 * .build(); 1109 * 1110 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 1111 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1112 * </p> 1113 * 1114 * <p> 1115 * This method is functionally equivalent to the following code: 1116 * <p class='bjava'> 1117 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).properties(<jv>properties</jv>).build()); 1118 * </p> 1119 * 1120 * <h5 class='section'>See Also:</h5><ul> 1121 * <li class='jma'>{@link Bean#properties()} / {@link Bean#p()} - On an annotation on the bean class itself. 1122 * </ul> 1123 * 1124 * @param beanClassName 1125 * The bean class name. 1126 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1127 * @param properties Comma-delimited list of property names. 1128 * @return This object. 1129 */ 1130 @FluentSetter 1131 public Builder beanProperties(String beanClassName, String properties) { 1132 return annotations(BeanAnnotation.create(beanClassName).p(properties).build()); 1133 } 1134 1135 /** 1136 * Bean property excludes. 1137 * 1138 * <p> 1139 * Specifies to exclude the specified list of properties for the specified bean class. 1140 * 1141 * <p> 1142 * Same as {@link #beanProperties(Class, String)} except you specify a list of bean property names that you want to exclude from 1143 * serialization. 1144 * 1145 * <p> 1146 * Setting applies to specified class and all subclasses. 1147 * 1148 * <h5 class='section'>Example:</h5> 1149 * <p class='bjava'> 1150 * <jc>// A bean with 3 properties.</jc> 1151 * <jk>public class</jk> MyBean { 1152 * <jk>public</jk> String 1153 * <jf>foo</jf> = <js>"foo"</js>, 1154 * <jf>bar</jf> = <js>"bar"</js>, 1155 * <jf>baz</jf> = <js>"baz"</js>; 1156 * } 1157 * 1158 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1159 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1160 * .<jsm>create</jsm>() 1161 * .beanPropertiesExcludes(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1162 * .build(); 1163 * 1164 * <jc>// Produces: {"foo":"foo"}</jc> 1165 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1166 * </p> 1167 * 1168 * <p> 1169 * This method is functionally equivalent to the following code: 1170 * <p class='bjava'> 1171 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).excludeProperties(<jv>properties</jv>).build()); 1172 * </p> 1173 * 1174 * <h5 class='section'>See Also:</h5><ul> 1175 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1176 * </ul> 1177 * 1178 * @param beanClass The bean class. 1179 * @param properties Comma-delimited list of property names. 1180 * @return This object. 1181 */ 1182 @FluentSetter 1183 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 1184 return annotations(BeanAnnotation.create(beanClass).xp(properties).build()); 1185 } 1186 1187 /** 1188 * Bean property excludes. 1189 * 1190 * <p> 1191 * Specifies to exclude the specified list of properties for the specified bean classes. 1192 * 1193 * <p> 1194 * Same as {@link #beanProperties(Map)} except you specify a list of bean property names that you want to exclude from 1195 * serialization. 1196 * 1197 * <p> 1198 * Setting applies to specified class and all subclasses. 1199 * 1200 * <h5 class='section'>Example:</h5> 1201 * <p class='bjava'> 1202 * <jc>// A bean with 3 properties.</jc> 1203 * <jk>public class</jk> MyBean { 1204 * <jk>public</jk> String 1205 * <jf>foo</jf> = <js>"foo"</js>, 1206 * <jf>bar</jf> = <js>"bar"</js>, 1207 * <jf>baz</jf> = <js>"baz"</js>; 1208 * } 1209 * 1210 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1211 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1212 * .<jsm>create</jsm>() 1213 * .beanPropertiesExcludes(AMap.of(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1214 * .build(); 1215 * 1216 * <jc>// Produces: {"foo":"foo"}</jc> 1217 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1218 * </p> 1219 * 1220 * <p> 1221 * This method is functionally equivalent to the following code for each entry: 1222 * <p class='bjava'> 1223 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).excludeProperties(<jv>value</jv>.toString()).build()); 1224 * </p> 1225 * 1226 * <h5 class='section'>See Also:</h5><ul> 1227 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1228 * </ul> 1229 * 1230 * @param values 1231 * The values to add to this builder. 1232 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1233 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1234 * @return This object. 1235 */ 1236 @FluentSetter 1237 public Builder beanPropertiesExcludes(Map<String,Object> values) { 1238 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).xp(stringify(v)).build())); 1239 return this; 1240 } 1241 1242 /** 1243 * Bean property excludes. 1244 * 1245 * <p> 1246 * Specifies to exclude the specified list of properties for the specified bean class. 1247 * 1248 * <p> 1249 * Same as {@link #beanPropertiesExcludes(String, String)} except you specify a list of bean property names that you want to exclude from 1250 * serialization. 1251 * 1252 * <p> 1253 * Setting applies to specified class and all subclasses. 1254 * 1255 * <h5 class='section'>Example:</h5> 1256 * <p class='bjava'> 1257 * <jc>// A bean with 3 properties.</jc> 1258 * <jk>public class</jk> MyBean { 1259 * <jk>public</jk> String 1260 * <jf>foo</jf> = <js>"foo"</js>, 1261 * <jf>bar</jf> = <js>"bar"</js>, 1262 * <jf>baz</jf> = <js>"baz"</js>; 1263 * } 1264 * 1265 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1266 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1267 * .<jsm>create</jsm>() 1268 * .beanPropertiesExcludes(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1269 * .build(); 1270 * 1271 * <jc>// Produces: {"foo":"foo"}</jc> 1272 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1273 * </p> 1274 * 1275 * <p> 1276 * This method is functionally equivalent to the following code: 1277 * <p class='bjava'> 1278 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).excludeProperties(<jv>properties</jv>).build()); 1279 * </p> 1280 * 1281 * <h5 class='section'>See Also:</h5><ul> 1282 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1283 * </ul> 1284 * 1285 * @param beanClassName 1286 * The bean class name. 1287 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1288 * @param properties Comma-delimited list of property names. 1289 * @return This object. 1290 */ 1291 @FluentSetter 1292 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 1293 return annotations(BeanAnnotation.create(beanClassName).xp(properties).build()); 1294 } 1295 1296 /** 1297 * Read-only bean properties. 1298 * 1299 * <p> 1300 * Specifies one or more properties on a bean that are read-only despite having valid getters. 1301 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1302 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1303 * for both serializers and parsers. 1304 * 1305 * <h5 class='section'>Example:</h5> 1306 * <p class='bjava'> 1307 * <jc>// A bean with 3 properties.</jc> 1308 * <jk>public class</jk> MyBean { 1309 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1310 * } 1311 * 1312 * <jc>// Create a serializer with read-only property settings.</jc> 1313 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1314 * .<jsm>create</jsm>() 1315 * .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1316 * .build(); 1317 * 1318 * <jc>// All 3 properties will be serialized.</jc> 1319 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1320 * 1321 * <jc>// Create a parser with read-only property settings.</jc> 1322 * ReaderParser <jv>parser</jv> = JsonParser 1323 * .<jsm>create</jsm>() 1324 * .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1325 * .ignoreUnknownBeanProperties() 1326 * .build(); 1327 * 1328 * <jc>// Parser ignores bar and baz properties.</jc> 1329 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1330 * </p> 1331 * 1332 * <p> 1333 * This method is functionally equivalent to the following code: 1334 * <p class='bjava'> 1335 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).readOnlyProperties(<jv>properties</jv>).build()); 1336 * </p> 1337 * 1338 * <h5 class='section'>See Also:</h5><ul> 1339 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1340 * </ul> 1341 * 1342 * @param beanClass The bean class. 1343 * @param properties Comma-delimited list of property names. 1344 * @return This object. 1345 */ 1346 @FluentSetter 1347 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 1348 return annotations(BeanAnnotation.create(beanClass).ro(properties).build()); 1349 } 1350 1351 /** 1352 * Read-only bean properties. 1353 * 1354 * <p> 1355 * Specifies one or more properties on beans that are read-only despite having valid getters. 1356 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1357 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1358 * for both serializers and parsers. 1359 * 1360 * <h5 class='section'>Example:</h5> 1361 * <p class='bjava'> 1362 * <jc>// A bean with 3 properties.</jc> 1363 * <jk>public class</jk> MyBean { 1364 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1365 * } 1366 * 1367 * <jc>// Create a serializer with read-only property settings.</jc> 1368 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1369 * .<jsm>create</jsm>() 1370 * .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1371 * .build(); 1372 * 1373 * <jc>// All 3 properties will be serialized.</jc> 1374 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1375 * 1376 * <jc>// Create a parser with read-only property settings.</jc> 1377 * ReaderParser <jv>parser</jv> = JsonParser 1378 * .<jsm>create</jsm>() 1379 * .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1380 * .ignoreUnknownBeanProperties() 1381 * .build(); 1382 * 1383 * <jc>// Parser ignores bar and baz properties.</jc> 1384 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1385 * </p> 1386 * 1387 * <p> 1388 * This method is functionally equivalent to the following code for each entry: 1389 * <p class='bjava'> 1390 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).readOnlyProperties(<jv>value</jv>.toString()).build()); 1391 * </p> 1392 * 1393 * <h5 class='section'>See Also:</h5><ul> 1394 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1395 * </ul> 1396 * 1397 * @param values 1398 * The values to add to this builder. 1399 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1400 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1401 * @return This object. 1402 */ 1403 @FluentSetter 1404 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 1405 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).ro(stringify(v)).build())); 1406 return this; 1407 } 1408 1409 /** 1410 * Read-only bean properties. 1411 * 1412 * <p> 1413 * Specifies one or more properties on a bean that are read-only despite having valid getters. 1414 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1415 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1416 * for both serializers and parsers. 1417 * 1418 * <h5 class='section'>Example:</h5> 1419 * <p class='bjava'> 1420 * <jc>// A bean with 3 properties.</jc> 1421 * <jk>public class</jk> MyBean { 1422 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1423 * } 1424 * 1425 * <jc>// Create a serializer with read-only property settings.</jc> 1426 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1427 * .<jsm>create</jsm>() 1428 * .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1429 * .build(); 1430 * 1431 * <jc>// All 3 properties will be serialized.</jc> 1432 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1433 * 1434 * <jc>// Create a parser with read-only property settings.</jc> 1435 * ReaderParser <jv>parser</jv> = JsonParser 1436 * .<jsm>create</jsm>() 1437 * .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1438 * .ignoreUnknownBeanProperties() 1439 * .build(); 1440 * 1441 * <jc>// Parser ignores bar and baz properties.</jc> 1442 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1443 * </p> 1444 * 1445 * <p> 1446 * This method is functionally equivalent to the following code: 1447 * <p class='bjava'> 1448 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).readOnlyProperties(<jv>properties</jv>).build()); 1449 * </p> 1450 * 1451 * <h5 class='section'>See Also:</h5><ul> 1452 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1453 * </ul> 1454 * 1455 * @param beanClassName 1456 * The bean class name. 1457 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1458 * @param properties Comma-delimited list of property names. 1459 * @return This object. 1460 */ 1461 @FluentSetter 1462 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 1463 return annotations(BeanAnnotation.create(beanClassName).ro(properties).build()); 1464 } 1465 1466 /** 1467 * Write-only bean properties. 1468 * 1469 * <p> 1470 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1471 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1472 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1473 * for both serializers and parsers. 1474 * 1475 * <h5 class='section'>Example:</h5> 1476 * <p class='bjava'> 1477 * <jc>// A bean with 3 properties.</jc> 1478 * <jk>public class</jk> MyBean { 1479 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1480 * } 1481 * 1482 * <jc>// Create a serializer with write-only property settings.</jc> 1483 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1484 * .<jsm>create</jsm>() 1485 * .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1486 * .build(); 1487 * 1488 * <jc>// Only foo will be serialized.</jc> 1489 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1490 * 1491 * <jc>// Create a parser with write-only property settings.</jc> 1492 * ReaderParser <jv>parser</jv> = JsonParser 1493 * .<jsm>create</jsm>() 1494 * .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1495 * .build(); 1496 * 1497 * <jc>// Parser parses all 3 properties.</jc> 1498 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1499 * </p> 1500 * 1501 * <p> 1502 * This method is functionally equivalent to the following code: 1503 * <p class='bjava'> 1504 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).writeOnlyProperties(<jv>properties</jv>).build()); 1505 * </p> 1506 * 1507 * <h5 class='section'>See Also:</h5><ul> 1508 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1509 * </ul> 1510 * 1511 * @param beanClass The bean class. 1512 * @param properties Comma-delimited list of property names. 1513 * @return This object. 1514 */ 1515 @FluentSetter 1516 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 1517 return annotations(BeanAnnotation.create(beanClass).wo(properties).build()); 1518 } 1519 1520 /** 1521 * Write-only bean properties. 1522 * 1523 * <p> 1524 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1525 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1526 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1527 * for both serializers and parsers. 1528 * 1529 * <h5 class='section'>Example:</h5> 1530 * <p class='bjava'> 1531 * <jc>// A bean with 3 properties.</jc> 1532 * <jk>public class</jk> MyBean { 1533 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1534 * } 1535 * 1536 * <jc>// Create a serializer with write-only property settings.</jc> 1537 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1538 * .<jsm>create</jsm>() 1539 * .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1540 * .build(); 1541 * 1542 * <jc>// Only foo will be serialized.</jc> 1543 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1544 * 1545 * <jc>// Create a parser with write-only property settings.</jc> 1546 * ReaderParser <jv>parser</jv> = JsonParser 1547 * .<jsm>create</jsm>() 1548 * .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1549 * .build(); 1550 * 1551 * <jc>// Parser parses all 3 properties.</jc> 1552 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1553 * </p> 1554 * 1555 * <p> 1556 * This method is functionally equivalent to the following code for each entry: 1557 * <p class='bjava'> 1558 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).writeOnlyProperties(<jv>value</jv>.toString()).build()); 1559 * </p> 1560 * 1561 * <h5 class='section'>See Also:</h5><ul> 1562 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1563 * </ul> 1564 * 1565 * @param values 1566 * The values to add to this builder. 1567 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1568 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1569 * @return This object. 1570 */ 1571 @FluentSetter 1572 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 1573 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).wo(stringify(v)).build())); 1574 return this; 1575 } 1576 1577 /** 1578 * Write-only bean properties. 1579 * 1580 * <p> 1581 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1582 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1583 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1584 * for both serializers and parsers. 1585 * 1586 * <h5 class='section'>Example:</h5> 1587 * <p class='bjava'> 1588 * <jc>// A bean with 3 properties.</jc> 1589 * <jk>public class</jk> MyBean { 1590 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1591 * } 1592 * 1593 * <jc>// Create a serializer with write-only property settings.</jc> 1594 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1595 * .<jsm>create</jsm>() 1596 * .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1597 * .build(); 1598 * 1599 * <jc>// Only foo will be serialized.</jc> 1600 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1601 * 1602 * <jc>// Create a parser with write-only property settings.</jc> 1603 * ReaderParser <jv>parser</jv> = JsonParser 1604 * .<jsm>create</jsm>() 1605 * .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1606 * .build(); 1607 * 1608 * <jc>// Parser parses all 3 properties.</jc> 1609 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1610 * </p> 1611 * 1612 * <p> 1613 * This method is functionally equivalent to the following code: 1614 * <p class='bjava'> 1615 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).writeOnlyProperties(<jv>properties</jv>).build()); 1616 * </p> 1617 * 1618 * <h5 class='section'>See Also:</h5><ul> 1619 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1620 * </ul> 1621 * 1622 * @param beanClassName 1623 * The bean class name. 1624 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1625 * @param properties Comma-delimited list of property names. 1626 * @return This object. 1627 */ 1628 @FluentSetter 1629 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 1630 return annotations(BeanAnnotation.create(beanClassName).wo(properties).build()); 1631 } 1632 1633 /** 1634 * Bean dictionary. 1635 * 1636 * <p> 1637 * The list of classes that make up the bean dictionary in this bean context. 1638 * 1639 * <p> 1640 * Values are prepended to the list so that later calls can override classes of earlier calls. 1641 * 1642 * <p> 1643 * A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred 1644 * through reflection. The names are defined through the {@link Bean#typeName() @Bean(typeName)} annotation defined 1645 * on the bean class. For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up 1646 * serialized as <js>"{_type:'myfoo',...}"</js> in JSON 1647 * or <js>"<myfoo>...</myfoo>"</js> in XML. 1648 * 1649 * <p> 1650 * This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes. 1651 * 1652 * <p> 1653 * Values can consist of any of the following types: 1654 * <ul> 1655 * <li>Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}. 1656 * <li>Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations. 1657 * <li>Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations. 1658 * <li>Any array or collection of the objects above. 1659 * </ul> 1660 * 1661 * <h5 class='section'>Example:</h5> 1662 * <p class='bjava'> 1663 * <jc>// POJOs with @Bean(name) annotations.</jc> 1664 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 1665 * <jk>public class</jk> Foo {...} 1666 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 1667 * <jk>public class</jk> Bar {...} 1668 * 1669 * <jc>// Create a parser and tell it which classes to try to resolve.</jc> 1670 * ReaderParser <jv>parser</jv> = JsonParser 1671 * .<jsm>create</jsm>() 1672 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 1673 * .addBeanTypes() 1674 * .build(); 1675 * 1676 * <jc>// A bean with a field with an indeterminate type.</jc> 1677 * <jk>public class</jk> MyBean { 1678 * <jk>public</jk> Object <jf>mySimpleField</jf>; 1679 * } 1680 * 1681 * <jc>// Parse bean.</jc> 1682 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>); 1683 * </p> 1684 * 1685 * <p> 1686 * Another option is to use the {@link Bean#dictionary()} annotation on the POJO class itself: 1687 * 1688 * <p class='bjava'> 1689 * <jc>// Instead of by parser, define a bean dictionary on a class through an annotation.</jc> 1690 * <jc>// This applies to all properties on this class and all subclasses.</jc> 1691 * <ja>@Bean</ja>(dictionary={Foo.<jk>class</jk>,Bar.<jk>class</jk>}) 1692 * <jk>public class</jk> MyBean { 1693 * <jk>public</jk> Object <jf>mySimpleField</jf>; <jc>// May contain Foo or Bar object.</jc> 1694 * <jk>public</jk> Map<String,Object> <jf>myMapField</jf>; <jc>// May contain Foo or Bar objects.</jc> 1695 * } 1696 * </p> 1697 * 1698 * <p> 1699 * A typical usage is to allow for HTML documents to be parsed back into HTML beans: 1700 * <p class='bjava'> 1701 * <jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc> 1702 * ReaderParser <jv>parser</jv> = HtmlParser 1703 * .<jsm>create</jsm>() 1704 * .dictionary(HtmlBeanDictionary.<jk>class</jk>) 1705 * .build(); 1706 * 1707 * <jc>// Parse an HTML body into HTML beans.</jc> 1708 * Body <jv>body</jv> = <jv>parser</jv>.parse(<js>"<body><ul><li>foo</li><li>bar</li></ul>"</js>, Body.<jk>class</jk>); 1709 * </p> 1710 * 1711 * <h5 class='section'>See Also:</h5><ul> 1712 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#dictionary()} 1713 * <li class='ja'>{@link org.apache.juneau.annotation.Beanp#dictionary()} 1714 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary()} 1715 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary_replace()} 1716 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} 1717 * </ul> 1718 * 1719 * @param values 1720 * The values to add to this setting. 1721 * @return This object. 1722 */ 1723 @FluentSetter 1724 public Builder beanDictionary(Class<?>...values) { 1725 return beanDictionary(alist(values)); 1726 } 1727 1728 /** 1729 * Same as {@link #beanDictionary(Class...)} but allows you to pass in a collection of classes. 1730 * 1731 * @param values 1732 * The values to add to this setting. 1733 * @return This object. 1734 * @see #beanDictionary(Class...) 1735 */ 1736 @FluentSetter 1737 public Builder beanDictionary(Collection<Class<?>> values) { 1738 beanDictionary().addAll(0, values); 1739 return this; 1740 } 1741 1742 /** 1743 * Returns the bean dictionary list. 1744 * 1745 * <p> 1746 * Gives access to the inner list if you need to make more than simple additions via {@link #beanDictionary(Class...)}. 1747 * 1748 * @return The bean dictionary list. 1749 * @see #beanDictionary(Class...) 1750 */ 1751 public List<Class<?>> beanDictionary() { 1752 if (beanDictionary == null) 1753 beanDictionary = list(); 1754 return beanDictionary; 1755 } 1756 1757 /** 1758 * Bean dictionary. 1759 * 1760 * <p> 1761 * This is identical to {@link #beanDictionary(Class...)}, but specifies a dictionary within the context of 1762 * a single class as opposed to globally. 1763 * 1764 * <h5 class='section'>Example:</h5> 1765 * <p class='bjava'> 1766 * <jc>// POJOs with @Bean(name) annotations.</jc> 1767 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 1768 * <jk>public class</jk> Foo {...} 1769 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 1770 * <jk>public class</jk> Bar {...} 1771 * 1772 * <jc>// A bean with a field with an indeterminate type.</jc> 1773 * <jk>public class</jk> MyBean { 1774 * <jk>public</jk> Object <jf>mySimpleField</jf>; 1775 * } 1776 * 1777 * <jc>// Create a parser and tell it which classes to try to resolve.</jc> 1778 * ReaderParser <jv>parser</jv> = JsonParser 1779 * .<jsm>create</jsm>() 1780 * .dictionaryOn(MyBean.<jk>class</jk>, Foo.<jk>class</jk>, Bar.<jk>class</jk>) 1781 * .build(); 1782 * 1783 * <jc>// Parse bean.</jc> 1784 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>); 1785 * </p> 1786 * 1787 * <p> 1788 * This is functionally equivalent to the {@link Bean#dictionary()} annotation. 1789 * 1790 * <h5 class='section'>See Also:</h5><ul> 1791 * <li class='jma'>{@link Bean#dictionary()} 1792 * <li class='jm'>{@link #beanDictionary(Class...)} 1793 * </ul> 1794 * 1795 * @param on The class that the dictionary values apply to. 1796 * @param values 1797 * The new values for this setting. 1798 * @return This object. 1799 */ 1800 @FluentSetter 1801 public Builder dictionaryOn(Class<?> on, Class<?>...values) { 1802 return annotations(BeanAnnotation.create(on).dictionary(values).build()); 1803 } 1804 1805 /** 1806 * POJO example. 1807 * 1808 * <p> 1809 * Specifies an example of the specified class. 1810 * 1811 * <p> 1812 * Examples are used in cases such as POJO examples in Swagger documents. 1813 * 1814 * <h5 class='section'>Example:</h5> 1815 * <p class='bjava'> 1816 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 1817 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1818 * .<jsm>create</jsm>() 1819 * .example(MyBean.<jk>class</jk>, <jk>new</jk> MyBean().setFoo(<js>"foo"</js>).setBar(123)) 1820 * .build(); 1821 * </p> 1822 * 1823 * <p> 1824 * This is a shorthand method for the following code: 1825 * <p class='bjava'> 1826 * <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(Json5.<jsf>DEFAULT</jsf>.toString(<jv>object</jv>)).build()) 1827 * </p> 1828 * 1829 * <h5 class='section'>Notes:</h5><ul> 1830 * <li class='note'>Using this method assumes the serialized form of the object is the same as that produced 1831 * by the default serializer. This may not be true based on settings or swaps on the constructed serializer. 1832 * </ul> 1833 * 1834 * <p> 1835 * POJO examples can also be defined on classes via the following: 1836 * <ul class='spaced-list'> 1837 * <li>The {@link Marshalled#example()} annotation on the class itself. 1838 * <li>A static field annotated with {@link Example @Example}. 1839 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 1840 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 1841 * </ul> 1842 * 1843 * @param <T> The POJO class. 1844 * @param pojoClass The POJO class. 1845 * @param o 1846 * An instance of the POJO class used for examples. 1847 * @return This object. 1848 */ 1849 @FluentSetter 1850 public <T> Builder example(Class<T> pojoClass, T o) { 1851 return annotations(MarshalledAnnotation.create(pojoClass).example(Json5.of(o)).build()); 1852 } 1853 1854 /** 1855 * POJO example. 1856 * 1857 * <p> 1858 * Specifies an example in JSON of the specified class. 1859 * 1860 * <p> 1861 * Examples are used in cases such as POJO examples in Swagger documents. 1862 * 1863 * <p> 1864 * Setting applies to specified class and all subclasses. 1865 * 1866 * <h5 class='section'>Example:</h5> 1867 * <p class='bjava'> 1868 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 1869 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1870 * .<jsm>create</jsm>() 1871 * .example(MyBean.<jk>class</jk>, <js>"{foo:'bar'}"</js>) 1872 * .build(); 1873 * </p> 1874 * 1875 * <p> 1876 * This is a shorthand method for the following code: 1877 * <p class='bjava'> 1878 * <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(<jv>json</jv>).build()) 1879 * </p> 1880 * 1881 * <p> 1882 * POJO examples can also be defined on classes via the following: 1883 * <ul class='spaced-list'> 1884 * <li>A static field annotated with {@link Example @Example}. 1885 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 1886 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 1887 * </ul> 1888 * 1889 * <h5 class='section'>See Also:</h5><ul> 1890 * <li class='ja'>{@link Marshalled#example()} 1891 * </ul> 1892 * 1893 * @param <T> The POJO class type. 1894 * @param pojoClass The POJO class. 1895 * @param json The JSON 5 representation of the example. 1896 * @return This object. 1897 */ 1898 @FluentSetter 1899 public <T> Builder example(Class<T> pojoClass, String json) { 1900 return annotations(MarshalledAnnotation.create(pojoClass).example(json).build()); 1901 } 1902 1903 /** 1904 * Find fluent setters. 1905 * 1906 * <p> 1907 * When enabled, fluent setters are detected on beans during parsing. 1908 * 1909 * <p> 1910 * Fluent setters must have the following attributes: 1911 * <ul> 1912 * <li>Public. 1913 * <li>Not static. 1914 * <li>Take in one parameter. 1915 * <li>Return the bean itself. 1916 * </ul> 1917 * 1918 * <h5 class='section'>Example:</h5> 1919 * <p class='bjava'> 1920 * <jc>// A bean with a fluent setter.</jc> 1921 * <jk>public class</jk> MyBean { 1922 * <jk>public</jk> MyBean foo(String <jv>value</jv>) {...} 1923 * } 1924 * 1925 * <jc>// Create a parser that finds fluent setters.</jc> 1926 * ReaderParser <jv>parser</jv> = JsonParser 1927 * .<jsm>create</jsm>() 1928 * .findFluentSetters() 1929 * .build(); 1930 * 1931 * <jc>// Parse into bean using fluent setter.</jc> 1932 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>); 1933 * </p> 1934 * 1935 * <h5 class='section'>Notes:</h5><ul> 1936 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used on methods to individually identify them as fluent setters. 1937 * <li class='note'>The {@link Bean#findFluentSetters() @Bean.fluentSetters()} annotation can also be used on classes to specify to look for fluent setters. 1938 * </ul> 1939 * 1940 * <h5 class='section'>See Also:</h5><ul> 1941 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#findFluentSetters()} 1942 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#findFluentSetters()} 1943 * </ul> 1944 * 1945 * @return This object. 1946 */ 1947 @FluentSetter 1948 public Builder findFluentSetters() { 1949 return findFluentSetters(true); 1950 } 1951 1952 /** 1953 * Same as {@link #findFluentSetters()} but allows you to explicitly specify the value. 1954 * 1955 * @param value The value for this setting. 1956 * @return This object. 1957 */ 1958 @FluentSetter 1959 public Builder findFluentSetters(boolean value) { 1960 findFluentSetters = value; 1961 return this; 1962 } 1963 1964 /** 1965 * Find fluent setters. 1966 * 1967 * <p> 1968 * Identical to {@link #findFluentSetters()} but enables it on a specific class only. 1969 * 1970 * <h5 class='section'>Example:</h5> 1971 * <p class='bjava'> 1972 * <jc>// A bean with a fluent setter.</jc> 1973 * <jk>public class</jk> MyBean { 1974 * <jk>public</jk> MyBean foo(String <jv>value</jv>) {...} 1975 * } 1976 * 1977 * <jc>// Create a parser that finds fluent setters.</jc> 1978 * ReaderParser <jv>parser</jv> = JsonParser 1979 * .<jsm>create</jsm>() 1980 * .findFluentSetters(MyBean.<jk>class</jk>) 1981 * .build(); 1982 * 1983 * <jc>// Parse into bean using fluent setter.</jc> 1984 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>); 1985 * </p> 1986 * 1987 * <h5 class='section'>Notes:</h5><ul> 1988 * <li class='note'>This method is functionally equivalent to using the {@link Bean#findFluentSetters()} annotation. 1989 * </ul> 1990 * 1991 * <h5 class='section'>See Also:</h5><ul> 1992 * <li class='ja'>{@link Bean#findFluentSetters()} 1993 * <li class='jm'>{@link #findFluentSetters()} 1994 * </ul> 1995 * 1996 * @param on The class that this applies to. 1997 * @return This object. 1998 */ 1999 @FluentSetter 2000 public Builder findFluentSetters(Class<?> on) { 2001 return annotations(BeanAnnotation.create(on).findFluentSetters(true).build()); 2002 } 2003 2004 /** 2005 * Ignore invocation errors on getters. 2006 * 2007 * <p> 2008 * When enabled, errors thrown when calling bean getter methods will silently be ignored. 2009 * Otherwise, a {@code BeanRuntimeException} is thrown. 2010 * 2011 * <h5 class='section'>Example:</h5> 2012 * <p class='bjava'> 2013 * <jc>// A bean with a property that throws an exception.</jc> 2014 * <jk>public class</jk> MyBean { 2015 * <jk>public</jk> String getFoo() { 2016 * <jk>throw new</jk> RuntimeException(<js>"foo"</js>); 2017 * } 2018 * } 2019 * 2020 * <jc>// Create a serializer that ignores bean getter exceptions.</jc> 2021 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2022 * .<jsm>create</jsm>() 2023 * .ingoreInvocationExceptionsOnGetters() 2024 * .build(); 2025 * 2026 * <jc>// Exception is ignored.</jc> 2027 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2028 * </p> 2029 * 2030 * <h5 class='section'>See Also:</h5><ul> 2031 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnGetters()} 2032 * </ul> 2033 * 2034 * @return This object. 2035 */ 2036 @FluentSetter 2037 public Builder ignoreInvocationExceptionsOnGetters() { 2038 return ignoreInvocationExceptionsOnGetters(true); 2039 } 2040 2041 /** 2042 * Same as {@link #ignoreInvocationExceptionsOnGetters()} but allows you to explicitly specify the value. 2043 * 2044 * @param value The value for this setting. 2045 * @return This object. 2046 */ 2047 @FluentSetter 2048 public Builder ignoreInvocationExceptionsOnGetters(boolean value) { 2049 ignoreInvocationExceptionsOnGetters = value; 2050 return this; 2051 } 2052 2053 /** 2054 * Ignore invocation errors on setters. 2055 * 2056 * <p> 2057 * When enabled, errors thrown when calling bean setter methods will silently be ignored. 2058 * Otherwise, a {@code BeanRuntimeException} is thrown. 2059 * 2060 * <h5 class='section'>Example:</h5> 2061 * <p class='bjava'> 2062 * <jc>// A bean with a property that throws an exception.</jc> 2063 * <jk>public class</jk> MyBean { 2064 * <jk>public void</jk> setFoo(String <jv>foo</jv>) { 2065 * <jk>throw new</jk> RuntimeException(<js>"foo"</js>); 2066 * } 2067 * } 2068 * 2069 * <jc>// Create a parser that ignores bean setter exceptions.</jc> 2070 * ReaderParser <jv>parser</jv> = JsonParser 2071 * .<jsm>create</jsm>() 2072 * .ignoreInvocationExceptionsOnSetters() 2073 * .build(); 2074 * 2075 * <jc>// Exception is ignored.</jc> 2076 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 2077 * </p> 2078 * 2079 * <h5 class='section'>See Also:</h5><ul> 2080 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnSetters()} 2081 * </ul> 2082 * 2083 * @return This object. 2084 */ 2085 @FluentSetter 2086 public Builder ignoreInvocationExceptionsOnSetters() { 2087 return ignoreInvocationExceptionsOnSetters(true); 2088 } 2089 2090 /** 2091 * Same as {@link #ignoreInvocationExceptionsOnSetters()} but allows you to explicitly specify the value. 2092 * 2093 * @param value The value for this setting. 2094 * @return This object. 2095 */ 2096 @FluentSetter 2097 public Builder ignoreInvocationExceptionsOnSetters(boolean value) { 2098 ignoreInvocationExceptionsOnSetters = value; 2099 return this; 2100 } 2101 2102 /** 2103 * Don't silently ignore missing setters. 2104 * 2105 * <p> 2106 * When enabled, trying to set a value on a bean property without a setter will throw a {@link BeanRuntimeException}. 2107 * Otherwise, it will be silently ignored. 2108 * 2109 * <h5 class='section'>Example:</h5> 2110 * <p class='bjava'> 2111 * <jc>// A bean with a property with a getter but not a setter.</jc> 2112 * <jk>public class</jk> MyBean { 2113 * <jk>public void</jk> getFoo() { 2114 * <jk>return</jk> <js>"foo"</js>; 2115 * } 2116 * } 2117 * 2118 * <jc>// Create a parser that throws an exception if a setter is not found but a getter is.</jc> 2119 * ReaderParser <jv>parser</jv> = JsonParser 2120 * .<jsm>create</jsm>() 2121 * .disableIgnoreMissingSetters() 2122 * .build(); 2123 * 2124 * <jc>// Throws a ParseException.</jc> 2125 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 2126 * </p> 2127 * 2128 * <h5 class='section'>Notes:</h5><ul> 2129 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters and fields to ignore them. 2130 * </ul> 2131 * 2132 * <h5 class='section'>See Also:</h5><ul> 2133 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreMissingSetters()} 2134 * </ul> 2135 * 2136 * @return This object. 2137 */ 2138 @FluentSetter 2139 public Builder disableIgnoreMissingSetters() { 2140 return disableIgnoreMissingSetters(true); 2141 } 2142 2143 /** 2144 * Same as {@link #disableIgnoreMissingSetters()} but allows you to explicitly specify the value. 2145 * 2146 * @param value The value for this setting. 2147 * @return This object. 2148 */ 2149 @FluentSetter 2150 public Builder disableIgnoreMissingSetters(boolean value) { 2151 disableIgnoreMissingSetters = value; 2152 return this; 2153 } 2154 2155 /** 2156 * Don't ignore transient fields. 2157 * 2158 * <p> 2159 * When enabled, methods and fields marked as <jk>transient</jk> will not be ignored as bean properties. 2160 * 2161 * <h5 class='section'>Example:</h5> 2162 * <p class='bjava'> 2163 * <jc>// A bean with a transient field.</jc> 2164 * <jk>public class</jk> MyBean { 2165 * <jk>public transient</jk> String <jf>foo</jf> = <js>"foo"</js>; 2166 * } 2167 * 2168 * <jc>// Create a serializer that doesn't ignore transient fields.</jc> 2169 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2170 * .<jsm>create</jsm>() 2171 * .disableIgnoreTransientFields() 2172 * .build(); 2173 * 2174 * <jc>// Produces: {"foo":"foo"}</jc> 2175 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2176 * </p> 2177 * 2178 * <h5 class='section'>Notes:</h5><ul> 2179 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used on transient fields to keep them from being ignored. 2180 * </ul> 2181 * 2182 * <h5 class='section'>See Also:</h5><ul> 2183 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreTransientFields()} 2184 * </ul> 2185 * 2186 * @return This object. 2187 */ 2188 @FluentSetter 2189 public Builder disableIgnoreTransientFields() { 2190 return disableIgnoreTransientFields(true); 2191 } 2192 2193 /** 2194 * Same as {@link #disableIgnoreTransientFields()} but allows you to explicitly specify the value. 2195 * 2196 * @param value The value for this setting. 2197 * @return This object. 2198 */ 2199 @FluentSetter 2200 public Builder disableIgnoreTransientFields(boolean value) { 2201 disableIgnoreTransientFields = value; 2202 return this; 2203 } 2204 2205 /** 2206 * Ignore unknown properties. 2207 * 2208 * <p> 2209 * When enabled, trying to set a value on a non-existent bean property will silently be ignored. 2210 * Otherwise, a {@code BeanRuntimeException} is thrown. 2211 * 2212 * <h5 class='section'>Example:</h5> 2213 * <p class='bjava'> 2214 * <jc>// A bean with a single property.</jc> 2215 * <jk>public class</jk> MyBean { 2216 * <jk>public</jk> String <jf>foo</jf>; 2217 * } 2218 * 2219 * <jc>// Create a parser that ignores missing bean properties.</jc> 2220 * ReaderParser <jv>parser</jv> = JsonParser 2221 * .<jsm>create</jsm>() 2222 * .ignoreUnknownBeanProperties() 2223 * .build(); 2224 * 2225 * <jc>// Doesn't throw an exception on unknown 'bar' property.</jc> 2226 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar'}"</js>, MyBean.<jk>class</jk>); 2227 * </p> 2228 * 2229 * <h5 class='section'>See Also:</h5><ul> 2230 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownBeanProperties()} 2231 * </ul> 2232 * 2233 * @return This object. 2234 */ 2235 @FluentSetter 2236 public Builder ignoreUnknownBeanProperties() { 2237 return ignoreUnknownBeanProperties(true); 2238 } 2239 2240 /** 2241 * Same as {@link #ignoreUnknownBeanProperties()} but allows you to explicitly specify the value. 2242 * 2243 * @param value The value for this setting. 2244 * @return This object. 2245 */ 2246 @FluentSetter 2247 public Builder ignoreUnknownBeanProperties(boolean value) { 2248 ignoreUnknownBeanProperties = value; 2249 return this; 2250 } 2251 2252 /** 2253 * Ignore unknown properties. 2254 * 2255 * <p> 2256 * When enabled, unknown enum values will be set to <jk>null</jk> instead of throwing an exception. 2257 * 2258 * <h5 class='section'>See Also:</h5><ul> 2259 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownEnumValues()} 2260 * </ul> 2261 * 2262 * @return This object. 2263 */ 2264 @FluentSetter 2265 public Builder ignoreUnknownEnumValues() { 2266 return ignoreUnknownEnumValues(true); 2267 } 2268 2269 /** 2270 * Same as {@link #ignoreUnknownEnumValues()} but allows you to explicitly specify the value. 2271 * 2272 * @param value The value for this setting. 2273 * @return This object. 2274 */ 2275 @FluentSetter 2276 public Builder ignoreUnknownEnumValues(boolean value) { 2277 ignoreUnknownEnumValues = value; 2278 return this; 2279 } 2280 2281 /** 2282 * Don't ignore unknown properties with null values. 2283 * 2284 * <p> 2285 * When enabled, trying to set a <jk>null</jk> value on a non-existent bean property will throw a {@link BeanRuntimeException}. 2286 * Otherwise it will be silently ignored. 2287 * 2288 * <h5 class='section'>Example:</h5> 2289 * <p class='bjava'> 2290 * <jc>// A bean with a single property.</jc> 2291 * <jk>public class</jk> MyBean { 2292 * <jk>public</jk> String <jf>foo</jf>; 2293 * } 2294 * 2295 * <jc>// Create a parser that throws an exception on an unknown property even if the value being set is null.</jc> 2296 * ReaderParser <jv>parser</jv> = JsonParser 2297 * .<jsm>create</jsm>() 2298 * .disableIgnoreUnknownNullBeanProperties() 2299 * .build(); 2300 * 2301 * <jc>// Throws a BeanRuntimeException wrapped in a ParseException on the unknown 'bar' property.</jc> 2302 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:null}"</js>, MyBean.<jk>class</jk>); 2303 * </p> 2304 * 2305 * <h5 class='section'>See Also:</h5><ul> 2306 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreUnknownNullBeanProperties()} 2307 * </ul> 2308 * 2309 * @return This object. 2310 */ 2311 @FluentSetter 2312 public Builder disableIgnoreUnknownNullBeanProperties() { 2313 return disableIgnoreUnknownNullBeanProperties(true); 2314 } 2315 2316 /** 2317 * Same as {@link #disableIgnoreUnknownNullBeanProperties()} but allows you to explicitly specify the value. 2318 * 2319 * @param value The value for this setting. 2320 * @return This object. 2321 */ 2322 @FluentSetter 2323 public Builder disableIgnoreUnknownNullBeanProperties(boolean value) { 2324 disableIgnoreUnknownNullBeanProperties = value; 2325 return this; 2326 } 2327 2328 /** 2329 * Implementation classes. 2330 * 2331 * <p> 2332 * For interfaces and abstract classes this method can be used to specify an implementation class for the 2333 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 2334 * parse). 2335 * 2336 * <h5 class='section'>Example:</h5> 2337 * <p class='bjava'> 2338 * <jc>// A bean interface.</jc> 2339 * <jk>public interface</jk> MyBean { 2340 * ... 2341 * } 2342 * 2343 * <jc>// A bean implementation.</jc> 2344 * <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean { 2345 * ... 2346 * } 2347 2348 * <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc> 2349 * ReaderParser <jv>parser</jv> = JsonParser 2350 * .<jsm>create</jsm>() 2351 * .implClass(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>) 2352 * .build(); 2353 * 2354 * <jc>// Instantiates a MyBeanImpl,</jc> 2355 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>); 2356 * </p> 2357 * 2358 * @param interfaceClass The interface class. 2359 * @param implClass The implementation class. 2360 * @return This object. 2361 */ 2362 @FluentSetter 2363 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 2364 return annotations(MarshalledAnnotation.create(interfaceClass).implClass(implClass).build()); 2365 } 2366 2367 /** 2368 * Implementation classes. 2369 * 2370 * <p> 2371 * For interfaces and abstract classes this method can be used to specify an implementation class for the 2372 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 2373 * parse). 2374 * 2375 * <h5 class='section'>Example:</h5> 2376 * <p class='bjava'> 2377 * <jc>// A bean with a single property.</jc> 2378 * <jk>public interface</jk> MyBean { 2379 * ... 2380 * } 2381 * 2382 * <jc>// A bean with a single property.</jc> 2383 * <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean { 2384 * ... 2385 * } 2386 2387 * <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc> 2388 * ReaderParser <jv>parser</jv> = JsonParser 2389 * .<jsm>create</jsm>() 2390 * .implClasses(AMap.<jsm>of</jsm>(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>)) 2391 * .build(); 2392 * 2393 * <jc>// Instantiates a MyBeanImpl,</jc> 2394 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>); 2395 * </p> 2396 * 2397 * @param values 2398 * The new value for this setting. 2399 * @return This object. 2400 */ 2401 @FluentSetter 2402 public Builder implClasses(Map<Class<?>,Class<?>> values) { 2403 values.forEach((k,v) -> annotations(MarshalledAnnotation.create(k).implClass(v).build())); 2404 return this; 2405 } 2406 2407 /** 2408 * Identifies a class to be used as the interface class for the specified class and all subclasses. 2409 * 2410 * <p> 2411 * When specified, only the list of properties defined on the interface class will be used during serialization. 2412 * Additional properties on subclasses will be ignored. 2413 * 2414 * <p class='bjava'> 2415 * <jc>// Parent class or interface</jc> 2416 * <jk>public abstract class</jk> A { 2417 * <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>; 2418 * } 2419 * 2420 * <jc>// Sub class</jc> 2421 * <jk>public class</jk> A1 <jk>extends</jk> A { 2422 * <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>; 2423 * } 2424 * 2425 * <jc>// Create a serializer and define our interface class mapping.</jc> 2426 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2427 * .<jsm>create</jsm>() 2428 * .interfaceClass(A1.<jk>class</jk>, A.<jk>class</jk>) 2429 * .build(); 2430 * 2431 * <jc>// Produces "{"foo":"foo"}"</jc> 2432 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1()); 2433 * </p> 2434 * 2435 * <p> 2436 * This annotation can be used on the parent class so that it filters to all child classes, or can be set 2437 * individually on the child classes. 2438 * 2439 * <h5 class='section'>Notes:</h5><ul> 2440 * <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. 2441 * </ul> 2442 * 2443 * @param on The class that the interface class applies to. 2444 * @param value 2445 * The new value for this setting. 2446 * @return This object. 2447 */ 2448 @FluentSetter 2449 public Builder interfaceClass(Class<?> on, Class<?> value) { 2450 return annotations(BeanAnnotation.create(on).interfaceClass(value).build()); 2451 } 2452 2453 /** 2454 * Identifies a set of interfaces. 2455 * 2456 * <p> 2457 * When specified, only the list of properties defined on the interface class will be used during serialization 2458 * of implementation classes. Additional properties on subclasses will be ignored. 2459 * 2460 * <p class='bjava'> 2461 * <jc>// Parent class or interface</jc> 2462 * <jk>public abstract class</jk> A { 2463 * <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>; 2464 * } 2465 * 2466 * <jc>// Sub class</jc> 2467 * <jk>public class</jk> A1 <jk>extends</jk> A { 2468 * <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>; 2469 * } 2470 * 2471 * <jc>// Create a serializer and define our interface class mapping.</jc> 2472 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2473 * .<jsm>create</jsm>() 2474 * .interfaces(A.<jk>class</jk>) 2475 * .build(); 2476 * 2477 * <jc>// Produces "{"foo":"foo"}"</jc> 2478 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1()); 2479 * </p> 2480 * 2481 * <p> 2482 * This annotation can be used on the parent class so that it filters to all child classes, or can be set 2483 * individually on the child classes. 2484 * 2485 * <h5 class='section'>Notes:</h5><ul> 2486 * <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. 2487 * </ul> 2488 * 2489 * @param value 2490 * The new value for this setting. 2491 * @return This object. 2492 */ 2493 @FluentSetter 2494 public Builder interfaces(Class<?>...value) { 2495 for (Class<?> v : value) 2496 annotations(BeanAnnotation.create(v).interfaceClass(v).build()); 2497 return this; 2498 } 2499 2500 /** 2501 * <i><l>Context</l> configuration property: </i> Locale. 2502 * 2503 * <p> 2504 * Specifies the default locale for serializer and parser sessions when not specified via {@link BeanSession.Builder#locale(Locale)}. 2505 * Typically used for POJO swaps that need to deal with locales such as swaps that convert <l>Date</l> and <l>Calendar</l> 2506 * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and 2507 * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods. 2508 * 2509 * <h5 class='section'>Example:</h5> 2510 * <p class='bjava'> 2511 * <jc>// Define a POJO swap that skips serializing beans if we're in the UK.</jc> 2512 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 2513 * <ja>@Override</ja> 2514 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 2515 * <jk>if</jk> (<jv>session</jv>.getLocale().equals(Locale.<jsf>UK</jsf>)) 2516 * <jk>return null</jk>; 2517 * <jk>return</jk> <jv>bean</jv>.toString(); 2518 * } 2519 * } 2520 * 2521 * <jc>// Create a serializer that uses the specified locale if it's not passed in through session args.</jc> 2522 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2523 * .<jsm>create</jsm>() 2524 * .locale(Locale.<jsf>UK</jsf>) 2525 * .swaps(MyBeanSwap.<jk>class</jk>) 2526 * .build(); 2527 * </p> 2528 * 2529 * <h5 class='section'>See Also:</h5><ul> 2530 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#locale()} 2531 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#locale(Locale)} 2532 * </ul> 2533 * 2534 * @param value The new value for this property. 2535 * @return This object. 2536 */ 2537 @FluentSetter 2538 public Builder locale(Locale value) { 2539 locale = value; 2540 return this; 2541 } 2542 2543 /** 2544 * <i><l>Context</l> configuration property: </i> Media type. 2545 * 2546 * <p> 2547 * Specifies the default media type for serializer and parser sessions when not specified via {@link BeanSession.Builder#mediaType(MediaType)}. 2548 * Typically used for POJO swaps that need to serialize the same POJO classes differently depending on 2549 * the specific requested media type. For example, a swap could handle a request for media types <js>"application/json"</js> 2550 * and <js>"application/json+foo"</js> slightly differently even though they're both being handled by the same JSON 2551 * serializer or parser. 2552 * 2553 * <h5 class='section'>Example:</h5> 2554 * <p class='bjava'> 2555 * <jc>// Define a POJO swap that skips serializing beans if the media type is application/json.</jc> 2556 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 2557 * <ja>@Override</ja> 2558 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 2559 * <jk>if</jk> (<jv>session</jv>.getMediaType().equals(<js>"application/json"</js>)) 2560 * <jk>return null</jk>; 2561 * <jk>return</jk> <jv>bean</jv>.toString(); 2562 * } 2563 * } 2564 * 2565 * <jc>// Create a serializer that uses the specified media type if it's not passed in through session args.</jc> 2566 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2567 * .<jsm>create</jsm>() 2568 * .mediaType(MediaType.<jsf>JSON</jsf>) 2569 * .build(); 2570 * </p> 2571 * 2572 * <h5 class='section'>See Also:</h5><ul> 2573 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#mediaType()} 2574 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#mediaType(MediaType)} 2575 * </ul> 2576 * 2577 * @param value The new value for this property. 2578 * @return This object. 2579 */ 2580 @FluentSetter 2581 public Builder mediaType(MediaType value) { 2582 mediaType = value; 2583 return this; 2584 } 2585 2586 /** 2587 * Bean class exclusions. 2588 * 2589 * <p> 2590 * List of classes that should not be treated as beans even if they appear to be bean-like. 2591 * Not-bean classes are converted to <c>Strings</c> during serialization. 2592 * 2593 * <p> 2594 * Values can consist of any of the following types: 2595 * <ul> 2596 * <li>Classes. 2597 * <li>Arrays and collections of classes. 2598 * </ul> 2599 * 2600 * <h5 class='section'>Example:</h5> 2601 * <p class='bjava'> 2602 * <jc>// A bean with a single property.</jc> 2603 * <jk>public class</jk> MyBean { 2604 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 2605 * 2606 * <jk>public</jk> String toString() { 2607 * <jk>return</jk> <js>"baz"</js>; 2608 * } 2609 * } 2610 * 2611 * <jc>// Create a serializer that doesn't treat MyBean as a bean class.</jc> 2612 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2613 * .<jsm>create</jsm>() 2614 * .notBeanClasses(MyBean.<jk>class</jk>) 2615 * .build(); 2616 * 2617 * <jc>// Produces "baz" instead of {"foo":"bar"}</jc> 2618 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2619 * </p> 2620 * 2621 * <h5 class='section'>Notes:</h5><ul> 2622 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on classes to prevent them from being recognized as beans. 2623 * </ul> 2624 * 2625 * <h5 class='section'>See Also:</h5><ul> 2626 * <li class='ja'>{@link org.apache.juneau.annotation.BeanIgnore} 2627 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#notBeanClasses()} 2628 * </ul> 2629 * 2630 * @param values 2631 * The values to add to this setting. 2632 * <br>Values can consist of any of the following types: 2633 * <ul> 2634 * <li>Classes. 2635 * <li>Arrays and collections of classes. 2636 * </ul> 2637 * @return This object. 2638 */ 2639 @FluentSetter 2640 public Builder notBeanClasses(Class<?>...values) { 2641 return notBeanClasses(alist(values)); 2642 } 2643 2644 /** 2645 * Same as {@link #notBeanClasses(Class...)} but allows you to pass in a collection of classes. 2646 * 2647 * @param values 2648 * The values to add to this setting. 2649 * @return This object. 2650 * @see #notBeanClasses(Class...) 2651 */ 2652 @FluentSetter 2653 public Builder notBeanClasses(Collection<Class<?>> values) { 2654 notBeanClasses().addAll(values); 2655 return this; 2656 } 2657 2658 /** 2659 * Returns the list of not-bean classes. 2660 * 2661 * <p> 2662 * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanClasses(Class...)}. 2663 * 2664 * @return The list of not-bean classes. 2665 * @see #notBeanClasses(Class...) 2666 */ 2667 public Set<Class<?>> notBeanClasses() { 2668 if (notBeanClasses == null) 2669 notBeanClasses = classSet(); 2670 return notBeanClasses; 2671 } 2672 2673 /** 2674 * Bean package exclusions. 2675 * 2676 * <p> 2677 * Used as a convenient way of defining the {@link #notBeanClasses(Class...)} property for entire packages. 2678 * Any classes within these packages will be serialized to strings using {@link Object#toString()}. 2679 * 2680 * <p> 2681 * Note that you can specify suffix patterns to include all subpackages. 2682 * 2683 * <p> 2684 * Values can consist of any of the following types: 2685 * <ul> 2686 * <li>Strings. 2687 * <li>Arrays and collections of strings. 2688 * </ul> 2689 * 2690 * <h5 class='section'>Example:</h5> 2691 * <p class='bjava'> 2692 * <jc>// Create a serializer that ignores beans in the specified packages.</jc> 2693 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2694 * .<jsm>create</jsm>() 2695 * .notBeanPackages(<js>"org.apache.foo"</js>, <js>"org.apache.bar.*"</js>) 2696 * .build(); 2697 * </p> 2698 * 2699 * @param values 2700 * The values to add to this setting. 2701 * <br>Values can consist of any of the following types: 2702 * <ul> 2703 * <li>{@link Package} objects. 2704 * <li>Strings. 2705 * <li>Arrays and collections of anything in this list. 2706 * </ul> 2707 * @return This object. 2708 */ 2709 @FluentSetter 2710 public Builder notBeanPackages(String...values) { 2711 return notBeanPackages(alist(values)); 2712 } 2713 2714 /** 2715 * Same as {@link #notBeanPackages(String...)} but allows you to pass in a collection of classes. 2716 * 2717 * @param values 2718 * The values to add to this setting. 2719 * @return This object. 2720 * @see #notBeanPackages(String...) 2721 */ 2722 @FluentSetter 2723 public Builder notBeanPackages(Collection<String> values) { 2724 notBeanPackages().addAll(values); 2725 return this; 2726 } 2727 2728 /** 2729 * Returns the list of not-bean Java package names. 2730 * 2731 * <p> 2732 * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanPackages(String...)}. 2733 * 2734 * @return The list of not-bean Java package names. 2735 * @see #notBeanPackages(String...) 2736 */ 2737 public Set<String> notBeanPackages() { 2738 if (notBeanPackages == null) 2739 notBeanPackages = new TreeSet<>(); 2740 return notBeanPackages; 2741 } 2742 2743 /** 2744 * Bean property namer 2745 * 2746 * <p> 2747 * The class to use for calculating bean property names. 2748 * 2749 * <p> 2750 * Predefined classes: 2751 * <ul> 2752 * <li>{@link BasicPropertyNamer} - Default. 2753 * <li>{@link PropertyNamerDLC} - Dashed-lower-case names. 2754 * <li>{@link PropertyNamerULC} - Dashed-upper-case names. 2755 * </ul> 2756 * 2757 * <h5 class='section'>Example:</h5> 2758 * <p class='bjava'> 2759 * <jc>// A bean with a single property.</jc> 2760 * <jk>public class</jk> MyBean { 2761 * <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>; 2762 * } 2763 * 2764 * <jc>// Create a serializer that uses Dashed-Lower-Case property names.</jc> 2765 * <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc> 2766 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2767 * .<jsm>create</jsm>() 2768 * .propertyNamer(PropertyNamerDLC.<jk>class</jk>) 2769 * .build(); 2770 * 2771 * <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc> 2772 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2773 * </p> 2774 * 2775 * @param value 2776 * The new value for this setting. 2777 * <br>The default is {@link BasicPropertyNamer}. 2778 * @return This object. 2779 */ 2780 @FluentSetter 2781 public Builder propertyNamer(Class<? extends PropertyNamer> value) { 2782 propertyNamer = value; 2783 return this; 2784 } 2785 2786 /** 2787 * Bean property namer 2788 * 2789 * <p> 2790 * Same as {@link #propertyNamer(Class)} but allows you to specify a namer for a specific class. 2791 * 2792 * <h5 class='section'>Example:</h5> 2793 * <p class='bjava'> 2794 * <jc>// A bean with a single property.</jc> 2795 * <jk>public class</jk> MyBean { 2796 * <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>; 2797 * } 2798 * 2799 * <jc>// Create a serializer that uses Dashed-Lower-Case property names for the MyBean class only.</jc> 2800 * <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc> 2801 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2802 * .<jsm>create</jsm>() 2803 * .propertyNamer(MyBean.<jk>class</jk>, PropertyNamerDLC.<jk>class</jk>) 2804 * .build(); 2805 * 2806 * <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc> 2807 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2808 * </p> 2809 * 2810 * <h5 class='section'>See Also:</h5><ul> 2811 * <li class='ja'>{@link Bean#propertyNamer() Bean(propertyNamer)} 2812 * <li class='jm'>{@link #propertyNamer(Class)} 2813 * </ul> 2814 * 2815 * @param on The class that the namer applies to. 2816 * @param value 2817 * The new value for this setting. 2818 * <br>The default is {@link BasicPropertyNamer}. 2819 * @return This object. 2820 */ 2821 @FluentSetter 2822 public Builder propertyNamer(Class<?> on, Class<? extends PropertyNamer> value) { 2823 return annotations(BeanAnnotation.create(on).propertyNamer(value).build()); 2824 } 2825 2826 /** 2827 * Sort bean properties. 2828 * 2829 * <p> 2830 * When enabled, all bean properties will be serialized and access in alphabetical order. 2831 * Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor. 2832 * On IBM JVMs, the bean properties are ordered based on their ordering in the Java file. 2833 * On Oracle JVMs, the bean properties are not ordered (which follows the official JVM specs). 2834 * 2835 * <p> 2836 * this setting is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations 2837 * to force bean properties to be in a particular order and can just alter the order of the fields/methods 2838 * in the Java file. 2839 * 2840 * <h5 class='section'>Example:</h5> 2841 * <p class='bjava'> 2842 * <jc>// A bean with 3 properties.</jc> 2843 * <jk>public class</jk> MyBean { 2844 * <jk>public</jk> String <jf>c</jf> = <js>"1"</js>; 2845 * <jk>public</jk> String <jf>b</jf> = <js>"2"</js>; 2846 * <jk>public</jk> String <jf>a</jf> = <js>"3"</js>; 2847 * } 2848 * 2849 * <jc>// Create a serializer that sorts bean properties.</jc> 2850 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2851 * .<jsm>create</jsm>() 2852 * .sortProperties() 2853 * .build(); 2854 * 2855 * <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc> 2856 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2857 * </p> 2858 * 2859 * <h5 class='section'>Notes:</h5><ul> 2860 * <li class='note'>The {@link Bean#sort() @Bean.sort()} annotation can also be used to sort properties on just a single class. 2861 * </ul> 2862 * 2863 * @return This object. 2864 */ 2865 @FluentSetter 2866 public Builder sortProperties() { 2867 sortProperties = true; 2868 return sortProperties(true); 2869 } 2870 2871 /** 2872 * Same as {@link #sortProperties()} but allows you to explicitly specify the value. 2873 * 2874 * @param value The value for this setting. 2875 * @return This object. 2876 */ 2877 @FluentSetter 2878 public Builder sortProperties(boolean value) { 2879 sortProperties = value; 2880 return this; 2881 } 2882 2883 /** 2884 * Sort bean properties. 2885 * 2886 * <p> 2887 * Same as {@link #sortProperties()} but allows you to specify individual bean classes instead of globally. 2888 * 2889 * <h5 class='section'>Example:</h5> 2890 * <p class='bjava'> 2891 * <jc>// A bean with 3 properties.</jc> 2892 * <jk>public class</jk> MyBean { 2893 * <jk>public</jk> String <jf>c</jf> = <js>"1"</js>; 2894 * <jk>public</jk> String <jf>b</jf> = <js>"2"</js>; 2895 * <jk>public</jk> String <jf>a</jf> = <js>"3"</js>; 2896 * } 2897 * 2898 * <jc>// Create a serializer that sorts properties on MyBean.</jc> 2899 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2900 * .<jsm>create</jsm>() 2901 * .sortProperties(MyBean.<jk>class</jk>) 2902 * .build(); 2903 * 2904 * <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc> 2905 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2906 * </p> 2907 * 2908 * <h5 class='section'>See Also:</h5><ul> 2909 * <li class='ja'>{@link Bean#sort() Bean(sort)} 2910 * <li class='jm'>{@link #sortProperties()} 2911 * </ul> 2912 * 2913 * @param on The bean classes to sort properties on. 2914 * @return This object. 2915 */ 2916 @FluentSetter 2917 public Builder sortProperties(Class<?>...on) { 2918 for (Class<?> c : on) 2919 annotations(BeanAnnotation.create(c).sort(true).build()); 2920 return this; 2921 } 2922 2923 /** 2924 * Identifies a stop class for the annotated class. 2925 * 2926 * <p> 2927 * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}. 2928 * Any properties in the stop class or in its base classes will be ignored during analysis. 2929 * 2930 * <p> 2931 * For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>, 2932 * but not <c>p1</c> or <c>p2</c>. 2933 * 2934 * <h5 class='section'>Example:</h5> 2935 * <p class='bjava'> 2936 * <jk>public class</jk> C1 { 2937 * <jk>public int</jk> getP1(); 2938 * } 2939 * 2940 * <jk>public class</jk> C2 <jk>extends</jk> C1 { 2941 * <jk>public int</jk> getP2(); 2942 * } 2943 * 2944 * <jk>public class</jk> C3 <jk>extends</jk> C2 { 2945 * <jk>public int</jk> getP3(); 2946 * } 2947 * 2948 * <jc>// Create a serializer specifies a stop class for C3.</jc> 2949 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2950 * .<jsm>create</jsm>() 2951 * .stopClass(C3.<jk>class</jk>, C2.<jk>class</jk>) 2952 * .build(); 2953 * 2954 * <jc>// Produces: {"p3":"..."}</jc> 2955 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> C3()); 2956 * </p> 2957 * 2958 * @param on The class on which the stop class is being applied. 2959 * @param value 2960 * The new value for this setting. 2961 * @return This object. 2962 */ 2963 @FluentSetter 2964 public Builder stopClass(Class<?> on, Class<?> value) { 2965 return annotations(BeanAnnotation.create(on).stopClass(value).build()); 2966 } 2967 2968 /** 2969 * Java object swaps. 2970 * 2971 * <p> 2972 * Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization, 2973 * and "swap in" the non-serializable class during parsing. 2974 * 2975 * <p> 2976 * An example of a swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string. 2977 * 2978 * <p> 2979 * Multiple swaps can be associated with a single class. 2980 * When multiple swaps are applicable to the same class, the media type pattern defined by 2981 * {@link ObjectSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match. 2982 * 2983 * <p> 2984 * Values can consist of any of the following types: 2985 * <ul> 2986 * <li>Any subclass of {@link ObjectSwap}. 2987 * <li>Any instance of {@link ObjectSwap}. 2988 * <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. 2989 * <li>Any array or collection of the objects above. 2990 * </ul> 2991 * 2992 * <h5 class='section'>Example:</h5> 2993 * <p class='bjava'> 2994 * <jc>// Sample swap for converting Dates to ISO8601 strings.</jc> 2995 * <jk>public class</jk> MyDateSwap <jk>extends</jk> StringSwap<Date> { 2996 * <jc>// ISO8601 formatter.</jc> 2997 * <jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>); 2998 * 2999 * <ja>@Override</ja> 3000 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, Date <jv>date</jv>) { 3001 * <jk>return</jk> <jf>format</jf>.format(<jv>date</jv>); 3002 * } 3003 * 3004 * <ja>@Override</ja> 3005 * <jk>public</jk> Date unswap(BeanSession <jv>session</jv>, String <jv>string</jv>, ClassMeta <jv>hint</jv>) <jk>throws</jk> Exception { 3006 * <jk>return</jk> <jf>format</jf>.parse(<jv>string</jv>); 3007 * } 3008 * } 3009 * 3010 * <jc>// Sample bean with a Date field.</jc> 3011 * <jk>public class</jk> MyBean { 3012 * <jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6); 3013 * } 3014 * 3015 * <jc>// Create a serializer that uses our date swap.</jc> 3016 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3017 * .<jsm>create</jsm>() 3018 * .swaps(MyDateSwap.<jk>class</jk>) 3019 * .build(); 3020 * 3021 * <jc>// Produces: {"date":"2012-03-03T04:05:06-0500"}</jc> 3022 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3023 * 3024 * <jc>// Create a serializer that uses our date swap.</jc> 3025 * ReaderParser <jv>parser</jv> = JsonParser 3026 * .<jsm>create</jsm>() 3027 * .swaps(MyDateSwap.<jk>class</jk>) 3028 * .build(); 3029 * 3030 * <jc>// Use our parser to parse a bean.</jc> 3031 * MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 3032 * </p> 3033 * 3034 * <h5 class='section'>Notes:</h5><ul> 3035 * <li class='note'>The {@link Swap @Swap} annotation can also be used on classes to identify swaps for the class. 3036 * <li class='note'>The {@link Swap @Swap} annotation can also be used on bean methods and fields to identify swaps for values of those bean properties. 3037 * </ul> 3038 * 3039 * @param values 3040 * The values to add to this setting. 3041 * <br>Values can consist of any of the following types: 3042 * <ul> 3043 * <li>Any subclass of {@link ObjectSwap}. 3044 * <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. 3045 * <li>Any array or collection of the objects above. 3046 * </ul> 3047 * @return This object. 3048 */ 3049 @FluentSetter 3050 public Builder swaps(Class<?>...values) { 3051 return swaps(alist(values)); 3052 } 3053 3054 /** 3055 * Same as {@link #swaps(Class...)} but allows you to pass in a collection of classes. 3056 * 3057 * @param values 3058 * The values to add to this setting. 3059 * @return This object. 3060 * @see #swaps(Class...) 3061 */ 3062 @FluentSetter 3063 public Builder swaps(Collection<Class<?>> values) { 3064 swaps().addAll(0, values); 3065 return this; 3066 } 3067 3068 /** 3069 * A shortcut for defining a {@link FunctionalSwap}. 3070 * 3071 * <h5 class='section'>Example:</h5> 3072 * <p class='bjava'> 3073 * <jc>// Create a serializer that performs a custom format for DAte objects.</jc> 3074 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3075 * .<jsm>create</jsm>() 3076 * .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -> <jsm>format</jsm>(<jv>x</jv>)) 3077 * .build(); 3078 * </p> 3079 * 3080 * @param <T> The object type being swapped out. 3081 * @param <S> The object type being swapped in. 3082 * @param normalClass The object type being swapped out. 3083 * @param swappedClass The object type being swapped in. 3084 * @param swapFunction The function to convert the object. 3085 * @return This object. 3086 */ 3087 @FluentSetter 3088 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 3089 return swap(normalClass, swappedClass, swapFunction, null); 3090 } 3091 3092 /** 3093 * A shortcut for defining a {@link FunctionalSwap}. 3094 * 3095 * <h5 class='section'>Example:</h5> 3096 * <p class='bjava'> 3097 * <jc>// Create a serializer that performs a custom format for Date objects.</jc> 3098 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3099 * .<jsm>create</jsm>() 3100 * .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -> <jsm>format</jsm>(<jv>x</jv>), <jv>x</jv> -> <jsm>parse</jsm>(<jv>x</jv>)) 3101 * .build(); 3102 * </p> 3103 * 3104 * @param <T> The object type being swapped out. 3105 * @param <S> The object type being swapped in. 3106 * @param normalClass The object type being swapped out. 3107 * @param swappedClass The object type being swapped in. 3108 * @param swapFunction The function to convert the object during serialization. 3109 * @param unswapFunction The function to convert the object during parsing. 3110 * @return This object. 3111 */ 3112 @FluentSetter 3113 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 3114 swaps().add(0, new FunctionalSwap<>(normalClass, swappedClass, swapFunction, unswapFunction)); 3115 return this; 3116 } 3117 3118 /** 3119 * Returns the bean swaps list. 3120 * 3121 * <p> 3122 * Gives access to the inner list if you need to make more than simple additions via {@link #swaps(Class...)}. 3123 * 3124 * @return The bean swaps list. 3125 * @see #swaps(Class...) 3126 */ 3127 public List<Object> swaps() { 3128 if (swaps == null) 3129 swaps = list(); 3130 return swaps; 3131 } 3132 3133 /** 3134 * <i><l>Context</l> configuration property: </i> TimeZone. 3135 * 3136 * <p> 3137 * Specifies the default time zone for serializer and parser sessions when not specified via {@link BeanSession.Builder#timeZone(TimeZone)}. 3138 * Typically used for POJO swaps that need to deal with timezones such as swaps that convert <l>Date</l> and <l>Calendar</l> 3139 * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and 3140 * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods. 3141 * 3142 * <h5 class='section'>Example:</h5> 3143 * <p class='bjava'> 3144 * <jc>// Define a POJO swap that skips serializing beans if the time zone is GMT.</jc> 3145 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 3146 * <ja>@Override</ja> 3147 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 3148 * <jk>if</jk> (<jv>session</jv>.getTimeZone().equals(TimeZone.<jsf>GMT</jsf>)) 3149 * <jk>return null</jk>; 3150 * <jk>return</jk> <jv>bean</jv>.toString(); 3151 * } 3152 * } 3153 * 3154 * <jc>// Create a serializer that uses GMT if the timezone is not specified in the session args.</jc> 3155 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3156 * .<jsm>create</jsm>() 3157 * .timeZone(TimeZone.<jsf>GMT</jsf>) 3158 * .build(); 3159 * </p> 3160 * 3161 * <h5 class='section'>See Also:</h5><ul> 3162 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#timeZone()} 3163 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#timeZone(TimeZone)} 3164 * </ul> 3165 * 3166 * @param value The new value for this property. 3167 * @return This object. 3168 */ 3169 @FluentSetter 3170 public Builder timeZone(TimeZone value) { 3171 timeZone = value; 3172 return this; 3173 } 3174 3175 /** 3176 * An identifying name for this class. 3177 * 3178 * <p> 3179 * The name is used to identify the class type during parsing when it cannot be inferred through reflection. 3180 * For example, if a bean property is of type <c>Object</c>, then the serializer will add the name to the 3181 * output so that the class can be determined during parsing. 3182 * 3183 * <p> 3184 * It is also used to specify element names in XML. 3185 * 3186 * <h5 class='section'>Example:</h5> 3187 * <p class='bjava'> 3188 * <jc>// Use _type='mybean' to identify this bean.</jc> 3189 * <jk>public class</jk> MyBean {...} 3190 * 3191 * <jc>// Create a serializer and specify the type name..</jc> 3192 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3193 * .<jsm>create</jsm>() 3194 * .typeName(MyBean.<jk>class</jk>, <js>"mybean"</js>) 3195 * .build(); 3196 * 3197 * <jc>// Produces: {"_type":"mybean",...}</jc> 3198 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3199 * </p> 3200 * 3201 * <h5 class='section'>Notes:</h5><ul> 3202 * <li class='note'>Equivalent to the {@link Bean#typeName() Bean(typeName)} annotation. 3203 * </ul> 3204 * 3205 * <h5 class='section'>See Also:</h5><ul> 3206 * <li class='jc'>{@link Bean#typeName() Bean(typeName)} 3207 * <li class='jm'>{@link #beanDictionary(Class...)} 3208 * </ul> 3209 * 3210 * @param on 3211 * The class the type name is being defined on. 3212 * @param value 3213 * The new value for this setting. 3214 * @return This object. 3215 */ 3216 @FluentSetter 3217 public Builder typeName(Class<?> on, String value) { 3218 return annotations(BeanAnnotation.create(on).typeName(value).build()); 3219 } 3220 3221 /** 3222 * Bean type property name. 3223 * 3224 * <p> 3225 * This specifies the name of the bean property used to store the dictionary name of a bean type so that the 3226 * parser knows the data type to reconstruct. 3227 * 3228 * <h5 class='section'>Example:</h5> 3229 * <p class='bjava'> 3230 * <jc>// POJOs with @Bean(name) annotations.</jc> 3231 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 3232 * <jk>public class</jk> Foo {...} 3233 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 3234 * <jk>public class</jk> Bar {...} 3235 * 3236 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3237 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3238 * .<jsm>create</jsm>() 3239 * .typePropertyName(<js>"t"</js>) 3240 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3241 * .build(); 3242 * 3243 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3244 * ReaderParser <jv>parser</jv> = JsonParser 3245 * .<jsm>create</jsm>() 3246 * .typePropertyName(<js>"t"</js>) 3247 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3248 * .build(); 3249 * 3250 * <jc>// A bean with a field with an indeterminate type.</jc> 3251 * <jk>public class</jk> MyBean { 3252 * <jk>public</jk> Object <jf>mySimpleField</jf>; 3253 * } 3254 * 3255 * <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc> 3256 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3257 * 3258 * <jc>// Parse bean.</jc> 3259 * MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 3260 * </p> 3261 * 3262 * <h5 class='section'>See Also:</h5><ul> 3263 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#typePropertyName()} 3264 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#typePropertyName()} 3265 * </ul> 3266 * 3267 * @param value 3268 * The new value for this setting. 3269 * <br>The default is <js>"_type"</js>. 3270 * @return This object. 3271 */ 3272 @FluentSetter 3273 public Builder typePropertyName(String value) { 3274 typePropertyName = value; 3275 return this; 3276 } 3277 3278 /** 3279 * Bean type property name. 3280 * 3281 * <p> 3282 * Same as {@link #typePropertyName(String)} except targets a specific bean class instead of globally. 3283 * 3284 * <h5 class='section'>Example:</h5> 3285 * <p class='bjava'> 3286 * <jc>// POJOs with @Bean(name) annotations.</jc> 3287 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 3288 * <jk>public class</jk> Foo {...} 3289 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 3290 * <jk>public class</jk> Bar {...} 3291 * 3292 * <jc>// A bean with a field with an indeterminate type.</jc> 3293 * <jk>public class</jk> MyBean { 3294 * <jk>public</jk> Object <jf>mySimpleField</jf>; 3295 * } 3296 * 3297 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3298 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3299 * .<jsm>create</jsm>() 3300 * .typePropertyName(MyBean.<jk>class</jk>, <js>"t"</js>) 3301 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3302 * .build(); 3303 * 3304 * <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc> 3305 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3306 * </p> 3307 * 3308 * <h5 class='section'>See Also:</h5><ul> 3309 * <li class='ja'>{@link Bean#typePropertyName() Bean(typePropertyName)} 3310 * </ul> 3311 * 3312 * @param on The class the type property name applies to. 3313 * @param value 3314 * The new value for this setting. 3315 * <br>The default is <js>"_type"</js>. 3316 * @return This object. 3317 */ 3318 @FluentSetter 3319 public Builder typePropertyName(Class<?> on, String value) { 3320 return annotations(BeanAnnotation.create(on).typePropertyName(value).build()); 3321 } 3322 3323 /** 3324 * Use enum names. 3325 * 3326 * <p> 3327 * When enabled, enums are always serialized by name, not using {@link Object#toString()}. 3328 * 3329 * <h5 class='section'>Example:</h5> 3330 * <p class='bjava'> 3331 * <jc>// Create a serializer with debug enabled.</jc> 3332 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3333 * .<jsm>create</jsm>() 3334 * .useEnumNames() 3335 * .build(); 3336 * 3337 * <jc>// Enum with overridden toString().</jc> 3338 * <jc>// Will be serialized as ONE/TWO/THREE even though there's a toString() method.</jc> 3339 * <jk>public enum</jk> Option { 3340 * <jsf>ONE</jsf>(1), 3341 * <jsf>TWO</jsf>(2), 3342 * <jsf>THREE</jsf>(3); 3343 * 3344 * <jk>private int</jk> <jf>value</jf>; 3345 * 3346 * Option(<jk>int</jk> <jv>value</jv>) { 3347 * <jk>this</jk>.<jf>value</jf> = <jv>value</jv>; 3348 * } 3349 * 3350 * <ja>@Override</ja> 3351 * <jk>public</jk> String toString() { 3352 * <jk>return</jk> String.<jsm>valueOf</jsm>(<jf>value</jf>); 3353 * } 3354 * } 3355 * </p> 3356 * 3357 * @return This object. 3358 */ 3359 @FluentSetter 3360 public Builder useEnumNames() { 3361 return useEnumNames(true); 3362 } 3363 3364 /** 3365 * Same as {@link #useEnumNames()} but allows you to explicitly specify the value. 3366 * 3367 * @param value The value for this setting. 3368 * @return This object. 3369 */ 3370 @FluentSetter 3371 public Builder useEnumNames(boolean value) { 3372 useEnumNames = value; 3373 return this; 3374 } 3375 3376 /** 3377 * Don't use interface proxies. 3378 * 3379 * <p> 3380 * When enabled, interfaces will be instantiated as proxy classes through the use of an 3381 * {@link InvocationHandler} if there is no other way of instantiating them. 3382 * Otherwise, throws a {@link BeanRuntimeException}. 3383 * 3384 * <h5 class='section'>See Also:</h5><ul> 3385 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableInterfaceProxies()} 3386 * </ul> 3387 * 3388 * @return This object. 3389 */ 3390 @FluentSetter 3391 public Builder disableInterfaceProxies() { 3392 return disableInterfaceProxies(true); 3393 } 3394 3395 /** 3396 * Same as {@link #disableInterfaceProxies()} but allows you to explicitly specify the value. 3397 * 3398 * @param value The value for this setting. 3399 * @return This object. 3400 */ 3401 @FluentSetter 3402 public Builder disableInterfaceProxies(boolean value) { 3403 disableInterfaceProxies = value; 3404 return this; 3405 } 3406 3407 /** 3408 * Use Java Introspector. 3409 * 3410 * <p> 3411 * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. 3412 * <br>Most {@link Bean @Bean} annotations will be ignored. 3413 * 3414 * <h5 class='section'>Example:</h5> 3415 * <p class='bjava'> 3416 * <jc>// Create a serializer that only uses the built-in java bean introspector for finding properties.</jc> 3417 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3418 * .<jsm>create</jsm>() 3419 * .useJavaBeanIntrospector() 3420 * .build(); 3421 * </p> 3422 * 3423 * @return This object. 3424 */ 3425 @FluentSetter 3426 public Builder useJavaBeanIntrospector() { 3427 return useJavaBeanIntrospector(true); 3428 } 3429 3430 /** 3431 * Same as {@link #useJavaBeanIntrospector()} but allows you to explicitly specify the value. 3432 * 3433 * @param value The value for this setting. 3434 * @return This object. 3435 */ 3436 @FluentSetter 3437 public Builder useJavaBeanIntrospector(boolean value) { 3438 useJavaBeanIntrospector = value; 3439 return this; 3440 } 3441 3442 // <FluentSetters> 3443 3444 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3445 public Builder annotations(Annotation...values) { 3446 super.annotations(values); 3447 return this; 3448 } 3449 3450 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3451 public Builder apply(AnnotationWorkList work) { 3452 super.apply(work); 3453 return this; 3454 } 3455 3456 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3457 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 3458 super.applyAnnotations(fromClasses); 3459 return this; 3460 } 3461 3462 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3463 public Builder applyAnnotations(Method...fromMethods) { 3464 super.applyAnnotations(fromMethods); 3465 return this; 3466 } 3467 3468 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3469 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 3470 super.cache(value); 3471 return this; 3472 } 3473 3474 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3475 public Builder debug() { 3476 super.debug(); 3477 return this; 3478 } 3479 3480 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3481 public Builder debug(boolean value) { 3482 super.debug(value); 3483 return this; 3484 } 3485 3486 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3487 public Builder impl(Context value) { 3488 super.impl(value); 3489 return this; 3490 } 3491 3492 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3493 public Builder type(Class<? extends org.apache.juneau.Context> value) { 3494 super.type(value); 3495 return this; 3496 } 3497 3498 // </FluentSetters> 3499 3500 //----------------------------------------------------------------------------------------------------------------- 3501 // Helpers 3502 //----------------------------------------------------------------------------------------------------------------- 3503 3504 private static Set<Class<?>> classSet() { 3505 return new TreeSet<>(Comparator.comparing(Class::getName)); 3506 } 3507 3508 private static Set<Class<?>> classSet(Collection<Class<?>> copy) { 3509 return classSet(copy, false); 3510 } 3511 3512 private static Set<Class<?>> classSet(Collection<Class<?>> copy, boolean nullIfEmpty) { 3513 if (copy == null || (nullIfEmpty && copy.isEmpty())) 3514 return null; 3515 Set<Class<?>> x = classSet(); 3516 x.addAll(copy); 3517 return x; 3518 } 3519 } 3520 3521 //----------------------------------------------------------------------------------------------------------------- 3522 // Instance 3523 //----------------------------------------------------------------------------------------------------------------- 3524 3525 final boolean 3526 beansRequireDefaultConstructor, 3527 beansRequireSerializable, 3528 beansRequireSettersForGetters, 3529 beansRequireSomeProperties, 3530 beanMapPutReturnsOldValue, 3531 useInterfaceProxies, 3532 ignoreUnknownBeanProperties, 3533 ignoreUnknownNullBeanProperties, 3534 ignoreUnknownEnumValues, 3535 ignoreMissingSetters, 3536 ignoreTransientFields, 3537 ignoreInvocationExceptionsOnGetters, 3538 ignoreInvocationExceptionsOnSetters, 3539 useJavaBeanIntrospector, 3540 useEnumNames, 3541 sortProperties, 3542 findFluentSetters; 3543 final Visibility 3544 beanConstructorVisibility, 3545 beanClassVisibility, 3546 beanMethodVisibility, 3547 beanFieldVisibility; 3548 final String typePropertyName; 3549 final Locale locale; 3550 final TimeZone timeZone; 3551 final MediaType mediaType; 3552 final Class<? extends PropertyNamer> propertyNamer; 3553 final List<Class<?>> beanDictionary, notBeanClasses; 3554 final List<Object> swaps; 3555 final List<String> notBeanPackages; 3556 final HashKey hashKey; 3557 3558 final Map<Class,ClassMeta> cmCache; 3559 3560 private final String[] notBeanPackageNames, notBeanPackagePrefixes; 3561 private final BeanRegistry beanRegistry; 3562 private final PropertyNamer propertyNamerBean; 3563 private final ObjectSwap[] swapArray; 3564 private final Class<?>[] notBeanClassesArray; 3565 private final ClassMeta<Object> cmObject; // Reusable ClassMeta that represents general Objects. 3566 private final ClassMeta<String> cmString; // Reusable ClassMeta that represents general Strings. 3567 private final ClassMeta<Class> cmClass; // Reusable ClassMeta that represents general Classes. 3568 3569 private final BeanSession defaultSession; 3570 private volatile WriterSerializer beanToStringSerializer; 3571 3572 /** 3573 * Constructor. 3574 * 3575 * @param builder The builder for this object. 3576 */ 3577 public BeanContext(Builder builder) { 3578 super(builder); 3579 3580 hashKey = builder.hashKey(); 3581 3582 beanConstructorVisibility = builder.beanConstructorVisibility; 3583 beanClassVisibility = builder.beanClassVisibility; 3584 beanMethodVisibility = builder.beanMethodVisibility; 3585 beanFieldVisibility = builder.beanFieldVisibility; 3586 beansRequireDefaultConstructor = builder.beansRequireDefaultConstructor; 3587 beansRequireSerializable = builder.beansRequireSerializable; 3588 beansRequireSettersForGetters = builder.beansRequireSettersForGetters; 3589 beansRequireSomeProperties = ! builder.disableBeansRequireSomeProperties; 3590 beanMapPutReturnsOldValue = builder.beanMapPutReturnsOldValue; 3591 useEnumNames = builder.useEnumNames; 3592 useInterfaceProxies = ! builder.disableInterfaceProxies; 3593 ignoreUnknownBeanProperties = builder.ignoreUnknownBeanProperties; 3594 ignoreUnknownNullBeanProperties = ! builder.disableIgnoreUnknownNullBeanProperties; 3595 ignoreUnknownEnumValues = builder.ignoreUnknownEnumValues; 3596 ignoreMissingSetters = ! builder.disableIgnoreMissingSetters; 3597 ignoreTransientFields = ! builder.disableIgnoreTransientFields; 3598 ignoreInvocationExceptionsOnGetters = builder.ignoreInvocationExceptionsOnGetters; 3599 ignoreInvocationExceptionsOnSetters = builder.ignoreInvocationExceptionsOnSetters; 3600 useJavaBeanIntrospector = builder.useJavaBeanIntrospector; 3601 sortProperties = builder.sortProperties; 3602 findFluentSetters = builder.findFluentSetters; 3603 typePropertyName = builder.typePropertyName != null ? builder.typePropertyName : "_type"; 3604 locale = builder.locale != null ? builder.locale : Locale.getDefault(); 3605 timeZone = builder.timeZone; 3606 mediaType = builder.mediaType; 3607 beanDictionary = optional(builder.beanDictionary).map(Collections::unmodifiableList).orElse(emptyList()); 3608 swaps = optional(builder.swaps).map(Collections::unmodifiableList).orElse(emptyList()); 3609 notBeanClasses = optional(builder.notBeanClasses).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); 3610 notBeanPackages = optional(builder.notBeanPackages).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); 3611 propertyNamer = builder.propertyNamer != null ? builder.propertyNamer : BasicPropertyNamer.class; 3612 3613 notBeanClassesArray = notBeanClasses.isEmpty() ? DEFAULT_NOTBEAN_CLASSES : Stream.of(notBeanClasses, alist(DEFAULT_NOTBEAN_CLASSES)).flatMap(Collection::stream).toArray(Class[]::new); 3614 3615 String[] _notBeanPackages = notBeanPackages.isEmpty() ? DEFAULT_NOTBEAN_PACKAGES : Stream.of(notBeanPackages, alist(DEFAULT_NOTBEAN_PACKAGES)).flatMap(Collection::stream).toArray(String[]::new); 3616 notBeanPackageNames = Stream.of(_notBeanPackages).filter(x -> ! x.endsWith(".*")).toArray(String[]::new); 3617 notBeanPackagePrefixes = Stream.of(_notBeanPackages).filter(x -> x.endsWith(".*")).map(x -> x.substring(0, x.length()-2)).toArray(String[]::new); 3618 3619 try { 3620 propertyNamerBean = propertyNamer.getDeclaredConstructor().newInstance(); 3621 } catch (Exception e) { 3622 throw asRuntimeException(e); 3623 } 3624 3625 LinkedList<ObjectSwap<?,?>> _swaps = new LinkedList<>(); 3626 swaps.forEach(x -> { 3627 if (x instanceof ObjectSwap) { 3628 _swaps.add((ObjectSwap<?,?>)x); 3629 } else { 3630 ClassInfo ci = ClassInfo.of((Class<?>)x); 3631 if (ci.isChildOf(ObjectSwap.class)) 3632 _swaps.add(BeanCreator.of(ObjectSwap.class).type(ci).run()); 3633 else if (ci.isChildOf(Surrogate.class)) 3634 _swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this)); 3635 else 3636 throw new BasicRuntimeException("Invalid class {0} specified in BeanContext.swaps property. Must be a subclass of ObjectSwap or Surrogate.", ci.inner()); 3637 } 3638 }); 3639 swapArray = _swaps.toArray(new ObjectSwap[_swaps.size()]); 3640 3641 cmCache = new ConcurrentHashMap<>(); 3642 cmCache.put(String.class, new ClassMeta(String.class, this, findObjectSwaps(String.class), findChildObjectSwaps(String.class))); 3643 cmCache.put(Object.class, new ClassMeta(Object.class, this, findObjectSwaps(Object.class), findChildObjectSwaps(Object.class))); 3644 cmString = cmCache.get(String.class); 3645 cmObject = cmCache.get(Object.class); 3646 cmClass = cmCache.get(Class.class); 3647 3648 beanRegistry = new BeanRegistry(this, null); 3649 defaultSession = createSession().unmodifiable().build(); 3650 } 3651 3652 @Override /* Context */ 3653 public Builder copy() { 3654 return new Builder(this); 3655 } 3656 3657 @Override /* Context */ 3658 public BeanSession.Builder createSession() { 3659 return BeanSession.create(this); 3660 } 3661 3662 @Override /* Context */ 3663 public BeanSession getSession() { 3664 return defaultSession; 3665 } 3666 3667 /** 3668 * Returns <jk>true</jk> if the specified bean context shares the same cache as this bean context. 3669 * 3670 * <p> 3671 * Useful for testing purposes. 3672 * 3673 * @param bc The bean context to compare to. 3674 * @return <jk>true</jk> if the bean contexts have equivalent settings and thus share caches. 3675 */ 3676 public final boolean hasSameCache(BeanContext bc) { 3677 return bc.cmCache == this.cmCache; 3678 } 3679 3680 /** 3681 * Wraps an object inside a {@link BeanMap} object (a modifiable {@link Map}). 3682 * 3683 * <p> 3684 * This is a shortcut for the following code: <c>createSession().build().toBeanMap(<jv>object</jv>);</c> 3685 * 3686 * <h5 class='section'>Example:</h5> 3687 * <p class='bjava'> 3688 * <jc>// Construct a bean map around a bean instance</jc> 3689 * BeanMap<Person> <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.toBeanMap(<jk>new</jk> Person()); 3690 * </p> 3691 * 3692 * @param <T> The class of the object being wrapped. 3693 * @param object The object to wrap in a map interface. Must not be null. 3694 * @return The wrapped object. 3695 * @see BeanSession#toBeanMap(Object) 3696 */ 3697 public <T> BeanMap<T> toBeanMap(T object) { 3698 return defaultSession.toBeanMap(object); 3699 } 3700 3701 /** 3702 * Creates a new {@link BeanMap} object (a modifiable {@link Map}) of the given class with uninitialized 3703 * property values. 3704 * 3705 * <p> 3706 * This is a shortcut for the following code: <c>createSession().build().newBeanMap(<jv>_class</jv>);</c> 3707 * 3708 * <h5 class='section'>Example:</h5> 3709 * <p class='bjava'> 3710 * <jc>// Construct a new bean map wrapped around a new Person object</jc> 3711 * BeanMap<Person> <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.newBeanMap(Person.<jk>class</jk>); 3712 * </p> 3713 * 3714 * @param <T> The class of the object being wrapped. 3715 * @param c The name of the class to create a new instance of. 3716 * @return A new instance of the class. 3717 * @see BeanSession#newBeanMap(Class) 3718 */ 3719 public <T> BeanMap<T> newBeanMap(Class<T> c) { 3720 return defaultSession.newBeanMap(c); 3721 } 3722 3723 /** 3724 * Converts the specified value to the specified class type. 3725 * 3726 * <p> 3727 * This is a shortcut for the following code: <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>);</c> 3728 * 3729 * @param <T> The class type to convert the value to. 3730 * @param value The value to convert. 3731 * @param type The class type to convert the value to. 3732 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3733 * @return The converted value. 3734 * @see BeanSession#convertToType(Object, Class) 3735 */ 3736 public final <T> T convertToType(Object value, Class<T> type) throws InvalidDataConversionException { 3737 return defaultSession.convertToType(value, type); 3738 } 3739 3740 /** 3741 * Same as {@link #convertToType(Object, Class)}, except used for instantiating inner member classes that must 3742 * be instantiated within another class instance. 3743 * 3744 * <p> 3745 * This is a shortcut for the following code: <c>createSession().build().convertToMemberType(<jv>outer</jv>, <jv>value</jv>, <jv>type</jv>);</c> 3746 * 3747 * @param <T> The class type to convert the value to. 3748 * @param outer 3749 * If class is a member class, this is the instance of the containing class. 3750 * Should be <jk>null</jk> if not a member class. 3751 * @param value The value to convert. 3752 * @param type The class type to convert the value to. 3753 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3754 * @return The converted value. 3755 * @see BeanSession#convertToMemberType(Object, Object, Class) 3756 */ 3757 public final <T> T convertToMemberType(Object outer, Object value, Class<T> type) throws InvalidDataConversionException { 3758 return defaultSession.convertToMemberType(outer, value, getClassMeta(type)); 3759 } 3760 3761 /** 3762 * Same as {@link #convertToType(Object, Class)}, but allows for complex data types consisting of collections or maps. 3763 * 3764 * <p> 3765 * This is a shortcut for the following code: <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>, <jv>args</jv>);</c> 3766 * 3767 * @param <T> The class type to convert the value to. 3768 * @param value The value to be converted. 3769 * @param type The target object type. 3770 * @param args The target object parameter types. 3771 * @return The converted type. 3772 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3773 * @see BeanSession#convertToType(Object, Type, Type...) 3774 */ 3775 public final <T> T convertToType(Object value, Type type, Type...args) throws InvalidDataConversionException { 3776 return (T)defaultSession.convertToMemberType(null, value, getClassMeta(type, args)); 3777 } 3778 3779 /** 3780 * Determines whether the specified class is ignored as a bean class based on the various exclusion parameters 3781 * specified on this context class. 3782 * 3783 * @param c The class type being tested. 3784 * @return <jk>true</jk> if the specified class matches any of the exclusion parameters. 3785 */ 3786 protected final boolean isNotABean(Class<?> c) { 3787 if (c.isArray() || c.isPrimitive() || c.isEnum() || c.isAnnotation()) 3788 return true; 3789 Package p = c.getPackage(); 3790 if (p != null) { 3791 for (String p2 : notBeanPackageNames) 3792 if (p.getName().equals(p2)) 3793 return true; 3794 for (String p2 : notBeanPackagePrefixes) 3795 if (p.getName().startsWith(p2)) 3796 return true; 3797 } 3798 ClassInfo ci = ClassInfo.of(c); 3799 for (Class exclude : notBeanClassesArray) 3800 if (ci.isChildOf(exclude)) 3801 return true; 3802 return false; 3803 } 3804 3805 /** 3806 * Returns <jk>true</jk> if the specified object is a bean. 3807 * 3808 * @param o The object to test. 3809 * @return <jk>true</jk> if the specified object is a bean. <jk>false</jk> if the bean is <jk>null</jk>. 3810 */ 3811 public boolean isBean(Object o) { 3812 if (o == null) 3813 return false; 3814 return getClassMetaForObject(o).isBean(); 3815 } 3816 3817 /** 3818 * Returns the {@link BeanMeta} class for the specified class. 3819 * 3820 * @param <T> The class type to get the meta-data on. 3821 * @param c The class to get the meta-data on. 3822 * @return 3823 * The {@link BeanMeta} for the specified class, or <jk>null</jk> if the class is not a bean per the settings on 3824 * this context. 3825 */ 3826 public final <T> BeanMeta<T> getBeanMeta(Class<T> c) { 3827 if (c == null) 3828 return null; 3829 return getClassMeta(c).getBeanMeta(); 3830 } 3831 3832 /** 3833 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 3834 * 3835 * @param <T> The class type being wrapped. 3836 * @param type The class to resolve. 3837 * @return 3838 * If the class is not an array, returns a cached {@link ClassMeta} object. 3839 * Otherwise, returns a new {@link ClassMeta} object every time. 3840 */ 3841 public final <T> ClassMeta<T> getClassMeta(Class<T> type) { 3842 return getClassMeta(type, true); 3843 } 3844 3845 /** 3846 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 3847 * 3848 * @param <T> The class type being wrapped. 3849 * @param type The class to resolve. 3850 * @param waitForInit 3851 * When enabled, wait for the ClassMeta constructor to finish before returning. 3852 * @return 3853 * If the class is not an array, returns a cached {@link ClassMeta} object. 3854 * Otherwise, returns a new {@link ClassMeta} object every time. 3855 */ 3856 final <T> ClassMeta<T> getClassMeta(Class<T> type, boolean waitForInit) { 3857 3858 // This can happen if we have transforms defined against String or Object. 3859 if (cmCache == null) 3860 return null; 3861 3862 ClassMeta<T> cm = cmCache.get(type); 3863 if (cm == null) { 3864 3865 synchronized (this) { 3866 // Make sure someone didn't already set it while this thread was blocked. 3867 cm = cmCache.get(type); 3868 if (cm == null) 3869 cm = new ClassMeta<>(type, this, findObjectSwaps(type), findChildObjectSwaps(type)); 3870 } 3871 } 3872 if (waitForInit) 3873 cm.waitForInit(); 3874 return cm; 3875 } 3876 3877 /** 3878 * Used to resolve <c>ClassMetas</c> of type <c>Collection</c> and <c>Map</c> that have 3879 * <c>ClassMeta</c> values that themselves could be collections or maps. 3880 * 3881 * <p> 3882 * <c>Collection</c> meta objects are assumed to be followed by zero or one meta objects indicating the element type. 3883 * 3884 * <p> 3885 * <c>Map</c> meta objects are assumed to be followed by zero or two meta objects indicating the key and value types. 3886 * 3887 * <p> 3888 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 3889 * 3890 * <h5 class='section'>Examples:</h5> 3891 * <ul> 3892 * <li><code>getClassMeta(String.<jk>class</jk>);</code> - A normal type. 3893 * <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list containing objects. 3894 * <li><code>getClassMeta(List.<jk>class</jk>, String.<jk>class</jk>);</code> - A list containing strings. 3895 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - A linked-list containing 3896 * strings. 3897 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - 3898 * A linked-list containing linked-lists of strings. 3899 * <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map containing object keys/values. 3900 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map 3901 * containing string keys/values. 3902 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> - 3903 * A map containing string keys and values of lists containing beans. 3904 * </ul> 3905 * 3906 * @param <T> 3907 * The class to resolve. 3908 * @param type 3909 * The class to resolve. 3910 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 3911 * @param args 3912 * The type arguments of the class if it's a collection or map. 3913 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 3914 * <br>Ignored if the main type is not a map or collection. 3915 * @return The resolved class meta. 3916 */ 3917 public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) { 3918 if (type == null) 3919 return null; 3920 ClassMeta<T> cm = type instanceof Class ? getClassMeta((Class)type) : resolveClassMeta(type, null); 3921 if (args.length == 0) 3922 return cm; 3923 ClassMeta<?>[] cma = new ClassMeta[args.length+1]; 3924 cma[0] = cm; 3925 for (int i = 0; i < Array.getLength(args); i++) { 3926 Type arg = (Type)Array.get(args, i); 3927 cma[i+1] = arg instanceof Class ? getClassMeta((Class)arg) : resolveClassMeta(arg, null); 3928 } 3929 return (ClassMeta<T>) getTypedClassMeta(cma, 0); 3930 } 3931 3932 /* 3933 * Resolves the 'genericized' class meta at the specified position in the ClassMeta array. 3934 */ 3935 private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) { 3936 ClassMeta<?> cm = c[pos++]; 3937 if (cm.isCollection() || cm.isOptional()) { 3938 ClassMeta<?> ce = c.length == pos ? object() : getTypedClassMeta(c, pos); 3939 return (ce.isObject() ? cm : new ClassMeta(cm, null, null, ce)); 3940 } else if (cm.isMap()) { 3941 ClassMeta<?> ck = c.length == pos ? object() : c[pos++]; 3942 ClassMeta<?> cv = c.length == pos ? object() : getTypedClassMeta(c, pos); 3943 return (ck.isObject() && cv.isObject() ? cm : new ClassMeta(cm, ck, cv, null)); 3944 } 3945 return cm; 3946 } 3947 3948 final ClassMeta resolveClassMeta(Type o, Map<Class<?>,Class<?>[]> typeVarImpls) { 3949 if (o == null) 3950 return null; 3951 3952 if (o instanceof ClassMeta) { 3953 ClassMeta<?> cm = (ClassMeta)o; 3954 3955 // This classmeta could have been created by a different context. 3956 // Need to re-resolve it to pick up ObjectSwaps and stuff on this context. 3957 if (cm.getBeanContext() == this) 3958 return cm; 3959 if (cm.isMap()) 3960 return getClassMeta(cm.innerClass, cm.getKeyType(), cm.getValueType()); 3961 if (cm.isCollection() || cm.isOptional()) 3962 return getClassMeta(cm.innerClass, cm.getElementType()); 3963 return getClassMeta(cm.innerClass); 3964 } 3965 3966 Class c = resolve(o, typeVarImpls); 3967 3968 // This can happen when trying to resolve the "E getFirst()" method on LinkedList, whose type is a TypeVariable 3969 // These should just resolve to Object. 3970 if (c == null) 3971 return object(); 3972 3973 ClassMeta rawType = getClassMeta(c); 3974 3975 // If this is a Map or Collection, and the parameter types aren't part 3976 // of the class definition itself (e.g. class AddressBook extends List<Person>), 3977 // then we need to figure out the parameters. 3978 if (rawType.isMap() || rawType.isCollection() || rawType.isOptional()) { 3979 ClassMeta[] params = findParameters(o, c); 3980 if (params == null) 3981 return rawType; 3982 if (rawType.isMap()) { 3983 if (params.length != 2 || (params[0].isObject() && params[1].isObject())) 3984 return rawType; 3985 return new ClassMeta(rawType, params[0], params[1], null); 3986 } 3987 if (rawType.isCollection() || rawType.isOptional()) { 3988 if (params.length != 1 || params[0].isObject()) 3989 return rawType; 3990 return new ClassMeta(rawType, null, null, params[0]); 3991 } 3992 } 3993 3994 if (rawType.isArray()) { 3995 if (o instanceof GenericArrayType) { 3996 GenericArrayType gat = (GenericArrayType)o; 3997 ClassMeta elementType = resolveClassMeta(gat.getGenericComponentType(), typeVarImpls); 3998 return new ClassMeta(rawType, null, null, elementType); 3999 } 4000 } 4001 4002 return rawType; 4003 } 4004 4005 /** 4006 * Convert a Type to a Class if possible. 4007 * Return null if not possible. 4008 */ 4009 final Class resolve(Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 4010 4011 if (t instanceof Class) 4012 return (Class)t; 4013 4014 if (t instanceof ParameterizedType) 4015 // A parameter (e.g. <String>. 4016 return (Class)((ParameterizedType)t).getRawType(); 4017 4018 if (t instanceof GenericArrayType) { 4019 // An array parameter (e.g. <byte[]>). 4020 Type gatct = ((GenericArrayType)t).getGenericComponentType(); 4021 4022 if (gatct instanceof Class) 4023 return Array.newInstance((Class)gatct, 0).getClass(); 4024 4025 if (gatct instanceof ParameterizedType) 4026 return Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass(); 4027 4028 if (gatct instanceof GenericArrayType) 4029 return Array.newInstance(resolve(gatct, typeVarImpls), 0).getClass(); 4030 4031 return null; 4032 4033 } else if (t instanceof TypeVariable) { 4034 if (typeVarImpls != null) { 4035 TypeVariable tv = (TypeVariable)t; 4036 String varName = tv.getName(); 4037 int varIndex = -1; 4038 Class gc = (Class)tv.getGenericDeclaration(); 4039 TypeVariable[] tvv = gc.getTypeParameters(); 4040 for (int i = 0; i < tvv.length; i++) { 4041 if (tvv[i].getName().equals(varName)) { 4042 varIndex = i; 4043 } 4044 } 4045 if (varIndex != -1) { 4046 4047 // If we couldn't find a type variable implementation, that means 4048 // the type was defined at runtime (e.g. Bean b = new Bean<Foo>();) 4049 // in which case the type is lost through erasure. 4050 // Assume java.lang.Object as the type. 4051 if (! typeVarImpls.containsKey(gc)) 4052 return null; 4053 4054 return typeVarImpls.get(gc)[varIndex]; 4055 } 4056 } 4057 } 4058 return null; 4059 } 4060 4061 final ClassMeta[] findParameters(Type o, Class c) { 4062 if (o == null) 4063 o = c; 4064 4065 // Loop until we find a ParameterizedType 4066 if (! (o instanceof ParameterizedType)) { 4067 loop: do { 4068 o = c.getGenericSuperclass(); 4069 if (o instanceof ParameterizedType) 4070 break loop; 4071 for (Type t : c.getGenericInterfaces()) { 4072 o = t; 4073 if (o instanceof ParameterizedType) 4074 break loop; 4075 } 4076 c = c.getSuperclass(); 4077 } while (c != null); 4078 } 4079 4080 if (o instanceof ParameterizedType) { 4081 ParameterizedType pt = (ParameterizedType)o; 4082 if (! pt.getRawType().equals(Enum.class)) { 4083 List<ClassMeta<?>> l = new LinkedList<>(); 4084 for (Type pt2 : pt.getActualTypeArguments()) { 4085 if (pt2 instanceof WildcardType || pt2 instanceof TypeVariable) 4086 return null; 4087 l.add(resolveClassMeta(pt2, null)); 4088 } 4089 if (l.isEmpty()) 4090 return null; 4091 return l.toArray(new ClassMeta[l.size()]); 4092 } 4093 } 4094 4095 return null; 4096 } 4097 4098 /** 4099 * Shortcut for calling {@code getClassMeta(o.getClass())}. 4100 * 4101 * @param <T> The class of the object being passed in. 4102 * @param o The class to find the class type for. 4103 * @return The ClassMeta object, or <jk>null</jk> if {@code o} is <jk>null</jk>. 4104 */ 4105 public final <T> ClassMeta<T> getClassMetaForObject(T o) { 4106 if (o == null) 4107 return null; 4108 return (ClassMeta<T>)getClassMeta(o.getClass()); 4109 } 4110 4111 4112 /** 4113 * Used for determining the class type on a method or field where a {@code @Beanp} annotation may be present. 4114 * 4115 * @param <T> The class type we're wrapping. 4116 * @param p The property annotation on the type if there is one. 4117 * @param t The type. 4118 * @param typeVarImpls 4119 * Contains known resolved type parameters on the specified class so that we can result 4120 * {@code ParameterizedTypes} and {@code TypeVariables}. 4121 * Can be <jk>null</jk> if the information is not known. 4122 * @return The new {@code ClassMeta} object wrapped around the {@code Type} object. 4123 */ 4124 protected final <T> ClassMeta<T> resolveClassMeta(Beanp p, Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 4125 ClassMeta<T> cm = resolveClassMeta(t, typeVarImpls); 4126 ClassMeta<T> cm2 = cm; 4127 4128 if (p != null) { 4129 4130 if (isNotVoid(p.type())) 4131 cm2 = resolveClassMeta(p.type(), typeVarImpls); 4132 4133 if (cm2.isMap()) { 4134 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class, Object.class} : p.params()); 4135 if (pParams.length != 2) 4136 throw new BasicRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length); 4137 ClassMeta<?> keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType()); 4138 ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType()); 4139 if (keyType.isObject() && valueType.isObject()) 4140 return cm2; 4141 return new ClassMeta<>(cm2, keyType, valueType, null); 4142 } 4143 4144 if (cm2.isCollection() || cm2.isOptional()) { 4145 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class} : p.params()); 4146 if (pParams.length != 1) 4147 throw new BasicRuntimeException("Invalid number of parameters specified for {1} (must be 1): {0}", pParams.length, (cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array")); 4148 ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType()); 4149 if (elementType.isObject()) 4150 return cm2; 4151 return new ClassMeta<>(cm2, null, null, elementType); 4152 } 4153 4154 return cm2; 4155 } 4156 4157 return cm; 4158 } 4159 4160 private ClassMeta<?> resolveType(Type...t) { 4161 for (Type tt : t) { 4162 if (tt != null) { 4163 ClassMeta<?> cm = getClassMeta(tt); 4164 if (tt != cmObject) 4165 return cm; 4166 } 4167 } 4168 return cmObject; 4169 } 4170 4171 /** 4172 * Returns the {@link ObjectSwap} associated with the specified class, or <jk>null</jk> if there is no POJO swap 4173 * associated with the class. 4174 * 4175 * @param <T> The class associated with the swap. 4176 * @param c The class associated with the swap. 4177 * @return The swap associated with the class, or null if there is no association. 4178 */ 4179 private final <T> ObjectSwap[] findObjectSwaps(Class<T> c) { 4180 // Note: On first 4181 if (c != null) { 4182 List<ObjectSwap> l = list(); 4183 for (ObjectSwap f : swapArray) 4184 if (f.getNormalClass().isParentOf(c)) 4185 l.add(f); 4186 return l.size() == 0 ? null : l.toArray(new ObjectSwap[l.size()]); 4187 } 4188 return null; 4189 } 4190 4191 /** 4192 * Checks whether a class has a {@link ObjectSwap} associated with it in this bean context. 4193 * 4194 * @param c The class to check. 4195 * @return <jk>true</jk> if the specified class or one of its subclasses has a {@link ObjectSwap} associated with it. 4196 */ 4197 private final ObjectSwap[] findChildObjectSwaps(Class<?> c) { 4198 if (c == null || swapArray.length == 0) 4199 return null; 4200 List<ObjectSwap> l = null; 4201 for (ObjectSwap f : swapArray) { 4202 if (f.getNormalClass().isChildOf(c)) { 4203 if (l == null) 4204 l = list(); 4205 l.add(f); 4206 } 4207 } 4208 return l == null ? null : l.toArray(new ObjectSwap[l.size()]); 4209 } 4210 4211 /** 4212 * Returns a reusable {@link ClassMeta} representation for the class <c>Object</c>. 4213 * 4214 * <p> 4215 * This <c>ClassMeta</c> is often used to represent "any object type" when an object type is not known. 4216 * 4217 * <p> 4218 * This method is identical to calling <code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to 4219 * avoid a hashmap lookup. 4220 * 4221 * @return The {@link ClassMeta} object associated with the <c>Object</c> class. 4222 */ 4223 protected final ClassMeta<Object> object() { 4224 return cmObject; 4225 } 4226 4227 /** 4228 * Returns a reusable {@link ClassMeta} representation for the class <c>String</c>. 4229 * 4230 * <p> 4231 * This <c>ClassMeta</c> is often used to represent key types in maps. 4232 * 4233 * <p> 4234 * This method is identical to calling <code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to 4235 * avoid a hashmap lookup. 4236 * 4237 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 4238 */ 4239 protected final ClassMeta<String> string() { 4240 return cmString; 4241 } 4242 4243 /** 4244 * Returns a reusable {@link ClassMeta} representation for the class <c>Class</c>. 4245 * 4246 * <p> 4247 * This <c>ClassMeta</c> is often used to represent key types in maps. 4248 * 4249 * <p> 4250 * This method is identical to calling <code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to 4251 * avoid a hashmap lookup. 4252 * 4253 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 4254 */ 4255 protected final ClassMeta<Class> _class() { 4256 return cmClass; 4257 } 4258 4259 /** 4260 * Returns the lookup table for resolving bean types by name. 4261 * 4262 * @return The lookup table for resolving bean types by name. 4263 */ 4264 protected final BeanRegistry getBeanRegistry() { 4265 return beanRegistry; 4266 } 4267 4268 //----------------------------------------------------------------------------------------------------------------- 4269 // Properties 4270 //----------------------------------------------------------------------------------------------------------------- 4271 4272 /** 4273 * Minimum bean class visibility. 4274 * 4275 * @see BeanContext.Builder#beanClassVisibility(Visibility) 4276 * @return 4277 * Classes are not considered beans unless they meet the minimum visibility requirements. 4278 */ 4279 public final Visibility getBeanClassVisibility() { 4280 return beanClassVisibility; 4281 } 4282 4283 /** 4284 * Minimum bean constructor visibility. 4285 * 4286 * @see BeanContext.Builder#beanConstructorVisibility(Visibility) 4287 * @return 4288 * Only look for constructors with this specified minimum visibility. 4289 */ 4290 public final Visibility getBeanConstructorVisibility() { 4291 return beanConstructorVisibility; 4292 } 4293 4294 /** 4295 * Bean dictionary. 4296 * 4297 * @see BeanContext.Builder#beanDictionary() 4298 * @return 4299 * The list of classes that make up the bean dictionary in this bean context. 4300 */ 4301 public final List<Class<?>> getBeanDictionary() { 4302 return beanDictionary; 4303 } 4304 4305 /** 4306 * Minimum bean field visibility. 4307 * 4308 * 4309 * @see BeanContext.Builder#beanFieldVisibility(Visibility) 4310 * @return 4311 * Only look for bean fields with this specified minimum visibility. 4312 */ 4313 public final Visibility getBeanFieldVisibility() { 4314 return beanFieldVisibility; 4315 } 4316 4317 /** 4318 * BeanMap.put() returns old property value. 4319 * 4320 * @see BeanContext.Builder#beanMapPutReturnsOldValue() 4321 * @return 4322 * <jk>true</jk> if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values. 4323 * <br>Otherwise, it returns <jk>null</jk>. 4324 */ 4325 public final boolean isBeanMapPutReturnsOldValue() { 4326 return beanMapPutReturnsOldValue; 4327 } 4328 4329 /** 4330 * Minimum bean method visibility. 4331 * 4332 * @see BeanContext.Builder#beanMethodVisibility(Visibility) 4333 * @return 4334 * Only look for bean methods with this specified minimum visibility. 4335 */ 4336 public final Visibility getBeanMethodVisibility() { 4337 return beanMethodVisibility; 4338 } 4339 4340 /** 4341 * Beans require no-arg constructors. 4342 * 4343 * @see BeanContext.Builder#beansRequireDefaultConstructor() 4344 * @return 4345 * <jk>true</jk> if a Java class must implement a default no-arg constructor to be considered a bean. 4346 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 4347 */ 4348 public final boolean isBeansRequireDefaultConstructor() { 4349 return beansRequireDefaultConstructor; 4350 } 4351 4352 /** 4353 * Beans require Serializable interface. 4354 * 4355 * @see BeanContext.Builder#beansRequireSerializable() 4356 * @return 4357 * <jk>true</jk> if a Java class must implement the {@link Serializable} interface to be considered a bean. 4358 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 4359 */ 4360 public final boolean isBeansRequireSerializable() { 4361 return beansRequireSerializable; 4362 } 4363 4364 /** 4365 * Beans require setters for getters. 4366 * 4367 * @see BeanContext.Builder#beansRequireSettersForGetters() 4368 * @return 4369 * <jk>true</jk> if only getters that have equivalent setters will be considered as properties on a bean. 4370 * <br>Otherwise, they are ignored. 4371 */ 4372 public final boolean isBeansRequireSettersForGetters() { 4373 return beansRequireSettersForGetters; 4374 } 4375 4376 /** 4377 * Beans require at least one property. 4378 * 4379 * @see BeanContext.Builder#disableBeansRequireSomeProperties() 4380 * @return 4381 * <jk>true</jk> if a Java class doesn't need to contain at least 1 property to be considered a bean. 4382 * <br>Otherwise, the bean is serialized as a string using the {@link Object#toString()} method. 4383 */ 4384 public final boolean isBeansRequireSomeProperties() { 4385 return beansRequireSomeProperties; 4386 } 4387 4388 /** 4389 * Bean type property name. 4390 * 4391 * @see BeanContext.Builder#typePropertyName(String) 4392 * @return 4393 * The name of the bean property used to store the dictionary name of a bean type so that the parser knows the data type to reconstruct. 4394 */ 4395 public final String getBeanTypePropertyName() { 4396 return typePropertyName; 4397 } 4398 4399 /** 4400 * Find fluent setters. 4401 * 4402 * <h5 class='section'>Description:</h5> 4403 * <p> 4404 * 4405 * @see BeanContext.Builder#findFluentSetters() 4406 * @return 4407 * <jk>true</jk> if fluent setters are detected on beans. 4408 */ 4409 public final boolean isFindFluentSetters() { 4410 return findFluentSetters; 4411 } 4412 4413 /** 4414 * Ignore invocation errors on getters. 4415 * 4416 * @see BeanContext.Builder#ignoreInvocationExceptionsOnGetters() 4417 * @return 4418 * <jk>true</jk> if errors thrown when calling bean getter methods are silently ignored. 4419 */ 4420 public final boolean isIgnoreInvocationExceptionsOnGetters() { 4421 return ignoreInvocationExceptionsOnGetters; 4422 } 4423 4424 /** 4425 * Ignore invocation errors on setters. 4426 * 4427 * @see BeanContext.Builder#ignoreInvocationExceptionsOnSetters() 4428 * @return 4429 * <jk>true</jk> if errors thrown when calling bean setter methods are silently ignored. 4430 */ 4431 public final boolean isIgnoreInvocationExceptionsOnSetters() { 4432 return ignoreInvocationExceptionsOnSetters; 4433 } 4434 4435 /** 4436 * Silently ignore missing setters. 4437 * 4438 * @see BeanContext.Builder#disableIgnoreMissingSetters() 4439 * @return 4440 * <jk>true</jk> if trying to set a value on a bean property without a setter should throw a {@link BeanRuntimeException}. 4441 */ 4442 public final boolean isIgnoreMissingSetters() { 4443 return ignoreMissingSetters; 4444 } 4445 4446 /** 4447 * Ignore transient fields. 4448 * 4449 * @see BeanContext.Builder#disableIgnoreTransientFields() 4450 * @return 4451 * <jk>true</jk> if fields and methods marked as transient should not be ignored. 4452 */ 4453 protected final boolean isIgnoreTransientFields() { 4454 return ignoreTransientFields; 4455 } 4456 4457 /** 4458 * Ignore unknown properties. 4459 * 4460 * @see BeanContext.Builder#ignoreUnknownBeanProperties() 4461 * @return 4462 * <jk>true</jk> if trying to set a value on a non-existent bean property is silently ignored. 4463 * <br>Otherwise, a {@code RuntimeException} is thrown. 4464 */ 4465 public final boolean isIgnoreUnknownBeanProperties() { 4466 return ignoreUnknownBeanProperties; 4467 } 4468 4469 /** 4470 * Ignore unknown enum values. 4471 * 4472 * @see BeanContext.Builder#ignoreUnknownEnumValues() 4473 * @return 4474 * <jk>true</jk> if unknown enum values should be set as <jk>null</jk> instead of throwing an exception. 4475 */ 4476 public final boolean isIgnoreUnknownEnumValues() { 4477 return ignoreUnknownEnumValues; 4478 } 4479 4480 /** 4481 * Ignore unknown properties with null values. 4482 * 4483 * @see BeanContext.Builder#disableIgnoreUnknownNullBeanProperties() 4484 * @return 4485 * <jk>true</jk> if trying to set a <jk>null</jk> value on a non-existent bean property should throw a {@link BeanRuntimeException}. 4486 */ 4487 public final boolean isIgnoreUnknownNullBeanProperties() { 4488 return ignoreUnknownNullBeanProperties; 4489 } 4490 4491 /** 4492 * Bean class exclusions. 4493 * 4494 * @see BeanContext.Builder#notBeanClasses(Class...) 4495 * @return 4496 * The list of classes that are explicitly not beans. 4497 */ 4498 protected final Class<?>[] getNotBeanClasses() { 4499 return notBeanClassesArray; 4500 } 4501 4502 /** 4503 * Bean package exclusions. 4504 * 4505 * @see BeanContext.Builder#notBeanPackages(String...) 4506 * @return 4507 * The list of fully-qualified package names to exclude from being classified as beans. 4508 */ 4509 public final String[] getNotBeanPackagesNames() { 4510 return notBeanPackageNames; 4511 } 4512 4513 /** 4514 * Bean package exclusions. 4515 * 4516 * @see BeanContext.Builder#notBeanPackages(String...) 4517 * @return 4518 * The list of package name prefixes to exclude from being classified as beans. 4519 */ 4520 protected final String[] getNotBeanPackagesPrefixes() { 4521 return notBeanPackagePrefixes; 4522 } 4523 4524 /** 4525 * Java object swaps. 4526 * 4527 * @see BeanContext.Builder#swaps(Class...) 4528 * @return 4529 * The list POJO swaps defined. 4530 */ 4531 public final ObjectSwap<?,?>[] getSwaps() { 4532 return swapArray; 4533 } 4534 4535 /** 4536 * Bean property namer. 4537 * 4538 * @see BeanContext.Builder#propertyNamer(Class) 4539 * @return 4540 * The interface used to calculate bean property names. 4541 */ 4542 public final PropertyNamer getPropertyNamer() { 4543 return propertyNamerBean; 4544 } 4545 4546 /** 4547 * Sort bean properties. 4548 * 4549 * @see BeanContext.Builder#sortProperties() 4550 * @return 4551 * <jk>true</jk> if all bean properties will be serialized and access in alphabetical order. 4552 */ 4553 public final boolean isSortProperties() { 4554 return sortProperties; 4555 } 4556 4557 /** 4558 * Use enum names. 4559 * 4560 * @see BeanContext.Builder#useEnumNames() 4561 * @return 4562 * <jk>true</jk> if enums are always serialized by name, not using {@link Object#toString()}. 4563 */ 4564 public final boolean isUseEnumNames() { 4565 return useEnumNames; 4566 } 4567 4568 /** 4569 * Use interface proxies. 4570 * 4571 * @see BeanContext.Builder#disableInterfaceProxies() 4572 * @return 4573 * <jk>true</jk> if interfaces will be instantiated as proxy classes through the use of an 4574 * {@link InvocationHandler} if there is no other way of instantiating them. 4575 */ 4576 public final boolean isUseInterfaceProxies() { 4577 return useInterfaceProxies; 4578 } 4579 4580 /** 4581 * Use Java Introspector. 4582 * 4583 * @see BeanContext.Builder#useJavaBeanIntrospector() 4584 * @return 4585 * <jk>true</jk> if the built-in Java bean introspector should be used for bean introspection. 4586 */ 4587 public final boolean isUseJavaBeanIntrospector() { 4588 return useJavaBeanIntrospector; 4589 } 4590 4591 /** 4592 * Locale. 4593 * 4594 * @see BeanContext.Builder#locale(Locale) 4595 * @return 4596 * The default locale for serializer and parser sessions. 4597 */ 4598 public final Locale getDefaultLocale() { 4599 return locale; 4600 } 4601 4602 /** 4603 * Media type. 4604 * 4605 * @see BeanContext.Builder#mediaType(MediaType) 4606 * @return 4607 * The default media type value for serializer and parser sessions. 4608 */ 4609 public final MediaType getDefaultMediaType() { 4610 return mediaType; 4611 } 4612 4613 /** 4614 * Time zone. 4615 * 4616 * @see BeanContext.Builder#timeZone(TimeZone) 4617 * @return 4618 * The default timezone for serializer and parser sessions. 4619 */ 4620 public final TimeZone getDefaultTimeZone() { 4621 return timeZone; 4622 } 4623 4624 /** 4625 * Returns the serializer to use for serializing beans when using the {@link BeanSession#convertToType(Object, Class)} 4626 * and related methods. 4627 * 4628 * @return The serializer. May be <jk>null</jk> if all initialization has occurred. 4629 */ 4630 protected WriterSerializer getBeanToStringSerializer() { 4631 if (beanToStringSerializer == null) { 4632 if (JsonSerializer.DEFAULT == null) 4633 return null; 4634 this.beanToStringSerializer = JsonSerializer.create().beanContext(this).sq().simpleAttrs().build(); 4635 } 4636 return beanToStringSerializer; 4637 } 4638 4639 //----------------------------------------------------------------------------------------------------------------- 4640 // Other methods 4641 //----------------------------------------------------------------------------------------------------------------- 4642 4643 @Override /* Context */ 4644 protected JsonMap properties() { 4645 return filteredMap() 4646 .append("id", System.identityHashCode(this)) 4647 .append("beanClassVisibility", beanClassVisibility) 4648 .append("beanConstructorVisibility", beanConstructorVisibility) 4649 .append("beanDictionary", beanDictionary) 4650 .append("beanFieldVisibility", beanFieldVisibility) 4651 .append("beanMethodVisibility", beanMethodVisibility) 4652 .append("beansRequireDefaultConstructor", beansRequireDefaultConstructor) 4653 .append("beansRequireSerializable", beansRequireSerializable) 4654 .append("beansRequireSettersForGetters", beansRequireSettersForGetters) 4655 .append("beansRequireSomeProperties", beansRequireSomeProperties) 4656 .append("ignoreTransientFields", ignoreTransientFields) 4657 .append("ignoreInvocationExceptionsOnGetters", ignoreInvocationExceptionsOnGetters) 4658 .append("ignoreInvocationExceptionsOnSetters", ignoreInvocationExceptionsOnSetters) 4659 .append("ignoreUnknownBeanProperties", ignoreUnknownBeanProperties) 4660 .append("ignoreUnknownNullBeanProperties", ignoreUnknownNullBeanProperties) 4661 .append("notBeanClasses", notBeanClasses) 4662 .append("notBeanPackageNames", notBeanPackageNames) 4663 .append("notBeanPackagePrefixes", notBeanPackagePrefixes) 4664 .append("swaps", swaps) 4665 .append("sortProperties", sortProperties) 4666 .append("useEnumNames", useEnumNames) 4667 .append("useInterfaceProxies", useInterfaceProxies) 4668 .append("useJavaBeanIntrospector", useJavaBeanIntrospector); 4669 } 4670}