001package io.avaje.jsonb; 002 003import io.avaje.jsonb.core.DefaultBootstrap; 004import io.avaje.jsonb.spi.AdapterFactory; 005import io.avaje.jsonb.spi.Bootstrap; 006import io.avaje.jsonb.spi.JsonStreamAdapter; 007import io.avaje.jsonb.spi.PropertyNames; 008 009import java.io.InputStream; 010import java.io.OutputStream; 011import java.io.Reader; 012import java.io.Writer; 013import java.lang.reflect.Type; 014import java.util.Iterator; 015import java.util.ServiceLoader; 016 017/** 018 * Provides access to json adapters by type. 019 * 020 * <h4>Initialise with defaults</h3> 021 * 022 * <pre>{@code 023 * Jsonb jsonb = Jsonb.builder().build(); 024 * }</pre> 025 * 026 * <h4>Initialise with some configuration</h3> 027 * 028 * <pre>{@code 029 * Jsonb jsonb = Jsonb.builder() 030 * .serializeNulls(true) 031 * .serializeEmpty(true) 032 * .failOnUnknown(true) 033 * .build(); 034 * }</pre> 035 * 036 * <h4>Initialise using Jackson core with configuration</h3> 037 * <p> 038 * We need to include the dependency <code>io.avaje:avaje-jsonb-jackson</code> to do this. 039 * This will use Jackson core JsonParser and JsonGenerator to do the underlying parsing and generation. 040 * </p> 041 * <pre>{@code 042 * 043 * // create the Jackson JsonFactory 044 * JsonFactory customFactory = ...; 045 * 046 * var jacksonAdapter = JacksonAdapter.builder() 047 * .serializeNulls(true) 048 * .jsonFactory(customFactory) 049 * .build(); 050 * 051 * Jsonb jsonb = Jsonb.builder() 052 * .adapter(jacksonAdapter) 053 * .build(); 054 * 055 * }</pre> 056 * 057 * <h4>fromJson</h4> 058 * <p> 059 * Read json content from: String, byte[], Reader, InputStream, JsonReader 060 * </p> 061 * <pre>{@code 062 * 063 * JsonType<Customer> customerType = jsonb.type(Customer.class); 064 * 065 * Customer customer = customerType.fromJson(content); 066 * 067 * }</pre> 068 * 069 * <h4>toJson</h4> 070 * <p> 071 * Write json content to: String, byte[], Writer, OutputStream, JsonWriter 072 * </p> 073 * <pre>{@code 074 * 075 * JsonType<Customer> customerType = jsonb.type(Customer.class); 076 * 077 * String asJson = customerType.toJson(customer); 078 * 079 * }</pre> 080 */ 081public interface Jsonb { 082 083 /** 084 * Create a new Jsonb.Builder to configure and build the Jsonb instance. 085 * <p> 086 * We can register JsonAdapter's to use for specific types before building and returning 087 * the Jsonb instance to use. 088 * <p> 089 * Note that JsonAdapter's that are generated are automatically registered via service 090 * loading so there is no need to explicitly register those generated JsonAdapters. 091 * 092 * <pre>{@code 093 * 094 * Jsonb jsonb = Jsonb.builder() 095 * .serializeNulls(true) 096 * .serializeEmpty(true) 097 * .failOnUnknown(true) 098 * .build(); 099 * 100 * }</pre> 101 */ 102 static Builder builder() { 103 Iterator<Bootstrap> bootstrapService = ServiceLoader.load(Bootstrap.class).iterator(); 104 if (bootstrapService.hasNext()) { 105 return bootstrapService.next().builder(); 106 } 107 return DefaultBootstrap.builder(); 108 } 109 110 /** 111 * Migrate to builder(). 112 */ 113 @Deprecated 114 static Builder newBuilder() { 115 return builder(); 116 } 117 118 /** 119 * Return json content for the given object. 120 * <p> 121 * This is a convenience method for {@code jsonb.type(Object.class).toJson(any) } 122 * 123 * @param any The object to return as json string 124 * @return Return json content for the given object. 125 */ 126 String toJson(Object any); 127 128 /** 129 * Return json content in pretty format for the given object. 130 * <p> 131 * This is a convenience method for {@code jsonb.type(Object.class).toJsonPretty(any) } 132 * 133 * @param any The object to return as json string in pretty format 134 * @return Return json content in pretty format for the given object. 135 */ 136 String toJsonPretty(Object any); 137 138 /** 139 * Return the value as json content in bytes form. 140 * <p> 141 * This is a convenience method for {@code jsonb.type(Object.class).toJsonBytes(any) } 142 */ 143 byte[] toJsonBytes(Object any); 144 145 /** 146 * Write to the given writer. 147 * <p> 148 * This is a convenience method for {@code jsonb.type(Object.class).toJson(any, writer) } 149 */ 150 void toJson(Object any, Writer writer); 151 152 /** 153 * Write to the given outputStream. 154 * <p> 155 * This is a convenience method for {@code jsonb.type(Object.class).toJsonBytes(any, outputStream) } 156 */ 157 void toJson(Object any, OutputStream outputStream); 158 159 /** 160 * Write to the given writer. 161 * <p> 162 * This is a convenience method for {@code jsonb.type(Object.class).toJson(any, writer) } 163 */ 164 void toJson(Object any, JsonWriter jsonWriter); 165 166 /** 167 * Return the JsonType used to read and write json for the given class. 168 * 169 * <h3>fromJson() example</h3> 170 * <pre>{@code 171 * 172 * Customer customer = jsonb 173 * .type(Customer.class) 174 * .fromJson(jsonContent); 175 * 176 * 177 * // list 178 * List<Customer> customers = jsonb 179 * .type(Customer.class) 180 * .list() 181 * .fromJson(jsonContent); 182 * 183 * }</pre> 184 * 185 * <h3>toJson() example</h3> 186 * <pre>{@code 187 * 188 * Object anything = ... 189 * String jsonContent = jsonb.toJson(anything); 190 * 191 * Customer customer = ... 192 * 193 * // any type toJson() 194 * String jsonContent = jsonb.toJson(customer); 195 * 196 * // or use .type(Customer.class) if we like 197 * String jsonContent = jsonb 198 * .type(Customer.class) 199 * .toJson(customer); 200 * 201 * }</pre> 202 * 203 * <h3>Using Object.class</h3> 204 * <p> 205 * We can use <code>type(Object.class)</code> when we don't know the specific type that is being 206 * written toJson or read fromJson. 207 * <p> 208 * 209 * <h3>Object toJson()</h3> 210 * <pre>{@code 211 * 212 * Object any = ... 213 * 214 * String jsonContent = jsonb 215 * .type(Object.class) 216 * .toJson(any); 217 * 218 * // which is the same as 219 * String jsonContent = jsonb.toJson(any); 220 * 221 * }</pre> 222 * <p> 223 * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter 224 * is determined dynamically based on the type of the object value passed in. 225 * <p> 226 * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in 227 * the result are determined dynamically based on the json types being read and the resulting java types 228 * are ArrayList, LinkedHashMap, String, boolean, and double. 229 */ 230 <T> JsonType<T> type(Class<T> cls); 231 232 /** 233 * Return the JsonType used to read and write json for the given type. 234 * <p> 235 * We can use {@link Types} to obtain common generic types for List, Set, Map, Array etc. 236 * 237 * <h3>Example</h3> 238 * <pre>{@code 239 * 240 * JsonType<List<String>> listOfStringType = jsonb.type(Types.listOf(String.class)) 241 * 242 * JsonType<List<Customer>> listOfCustomerType = jsonb.type(Types.listOf(Customer.class)) 243 * 244 * JsonType<Map<String,Integer>> adapter = jsonb.type(Types.mapOf(Integer.class)) 245 * 246 * }</pre> 247 * 248 * <h3>Using Object.class</h3> 249 * <p> 250 * We can use <code>type(Object.class)</code> when we don't know the specific type that is being 251 * written toJson or read fromJson. 252 * 253 * <h3>Object toJson()</h3> 254 * <pre>{@code 255 * 256 * Object any = ... 257 * 258 * String jsonContent = jsonb 259 * .type(Object.class) 260 * .toJson(any); 261 * 262 * // the same as 263 * String jsonContent = jsonb.toJson(any); 264 * 265 * }</pre> 266 * <p> 267 * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter 268 * is determined dynamically based on the type of the object value passed in. 269 * <p> 270 * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in 271 * the result are determined dynamically based on the json types being read and the resulting java types 272 * are ArrayList, LinkedHashMap, String, boolean, and double. 273 */ 274 <T> JsonType<T> type(Type type); 275 276 /** 277 * Return the JsonType for the given value using the class of the value being passed in. 278 * <p> 279 * This is a helper method that supports returning an inferred generic type. 280 * 281 * @param value The value of the given type 282 * @param <T> The inferred generic parameter type 283 * @return JsonType for the given value 284 */ 285 <T> JsonType<T> typeOf(Object value); 286 287 /** 288 * Return the JsonReader used to read the given json content. 289 */ 290 JsonReader reader(String json); 291 292 /** 293 * Return the JsonReader used to read the given json content in bytes. 294 */ 295 JsonReader reader(byte[] jsonBytes); 296 297 /** 298 * Return the JsonReader used to read the json content from the given reader. 299 */ 300 JsonReader reader(Reader reader); 301 302 /** 303 * Return the JsonReader used to read the json content from the given inputStream. 304 */ 305 JsonReader reader(InputStream inputStream); 306 307 /** 308 * Return the JsonWriter used to write json to the given writer. 309 */ 310 JsonWriter writer(Writer writer); 311 312 /** 313 * Return the JsonWriter used to write json to the given outputStream. 314 */ 315 JsonWriter writer(OutputStream outputStream); 316 317 /** 318 * Return the property names as PropertyNames. 319 * <p> 320 * Provides the option of optimising the writing of json for property names 321 * by having them already escaped and encoded rather than as plain strings. 322 */ 323 PropertyNames properties(String... names); 324 325 /** 326 * Return the JsonAdapter used to read and write json for the given class. 327 * <p> 328 * JsonAdapter is generally used by generated code and your application code 329 * is expected to use {@link Jsonb#type(Class)} and {@link JsonType} instead. 330 */ 331 <T> JsonAdapter<T> adapter(Class<T> cls); 332 333 /** 334 * Return the JsonAdapter used to read and write json for the given type. 335 * <p> 336 * JsonAdapter is generally used by generated code and your application code 337 * is expected to use {@link Jsonb#type(Type)} and {@link JsonType} instead. 338 */ 339 <T> JsonAdapter<T> adapter(Type type); 340 341 /** 342 * Raw JsonAdapter for raw json content. 343 */ 344 JsonAdapter<String> rawAdapter(); 345 346 /** 347 * Build the Jsonb instance adding JsonAdapter, Factory or AdapterBuilder. 348 */ 349 interface Builder { 350 351 /** 352 * Set to serialise null values or not. 353 * <p> 354 * Default is to not serialise nulls. 355 */ 356 Builder serializeNulls(boolean serializeNulls); 357 358 /** 359 * Set to serialise empty collections or not. 360 * <p> 361 * Default is to not serialise empty collections. 362 */ 363 Builder serializeEmpty(boolean serializeEmpty); 364 365 /** 366 * Set failOnUnknown to true such that an exception is thrown when unknown 367 * properties are read in the json content. 368 */ 369 Builder failOnUnknown(boolean failOnUnknown); 370 371 /** 372 * Set to true for BigDecimal and BigInteger to serialise as String values rather than number values. 373 */ 374 Builder mathTypesAsString(boolean mathTypesAsString); 375 376 /** 377 * Explicitly set the adapter to use. 378 * <p> 379 * When not set the JsonStreamAdapter is service loaded using {@link AdapterFactory} 380 * with a fallback default of using the builtin implementation. 381 * 382 * @param streamAdapter The underlying adapter to use when generating and parsing 383 */ 384 Builder adapter(JsonStreamAdapter streamAdapter); 385 386 /** 387 * Add a JsonAdapter to use for the given type. 388 */ 389 <T> Builder add(Type type, JsonAdapter<T> jsonAdapter); 390 391 /** 392 * Add a AdapterBuilder which provides a JsonAdapter to use for the given type. 393 */ 394 Builder add(Type type, AdapterBuilder builder); 395 396 /** 397 * Add a Component which can provide multiple JsonAdapters and or configuration. 398 */ 399 Builder add(JsonbComponent component); 400 401 /** 402 * Add a JsonAdapter.Factory which provides JsonAdapters to use. 403 */ 404 Builder add(JsonAdapter.Factory factory); 405 406 /** 407 * Build and return the Jsonb instance with all the given adapters and factories registered. 408 */ 409 Jsonb build(); 410 } 411 412 /** 413 * Function to build a JsonAdapter that needs Jsonb. 414 */ 415 @FunctionalInterface 416 interface AdapterBuilder { 417 418 /** 419 * Create a JsonAdapter given the Jsonb instance. 420 */ 421 JsonAdapter<?> build(Jsonb jsonb); 422 } 423 424 /** 425 * Components register JsonAdapters Jsonb.Builder 426 */ 427 @FunctionalInterface 428 interface GeneratedComponent extends JsonbComponent { 429 430 /** 431 * Register JsonAdapters with the Builder. 432 */ 433 void register(Builder builder); 434 } 435}