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 * Customer customer = ... 189 * 190 * String jsonContent = jsonb 191 * .type(Customer.class) 192 * .toJson(customer); 193 * 194 * }</pre> 195 * 196 * <h3>Using Object.class</h3> 197 * <p> 198 * We can use <code>type(Object.class)</code> when we don't know the specific type that is being 199 * written toJson or read fromJson. 200 * <p> 201 * 202 * <h3>Object toJson()</h3> 203 * <pre>{@code 204 * 205 * Object any = ... 206 * 207 * String jsonContent = jsonb 208 * .type(Object.class) 209 * .toJson(any); 210 * 211 * // the same as 212 * String jsonContent = jsonb.toJson(any); 213 * 214 * }</pre> 215 * <p> 216 * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter 217 * is determined dynamically based on the type of the object value passed in. 218 * <p> 219 * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in 220 * the result are determined dynamically based on the json types being read and the resulting java types 221 * are ArrayList, LinkedHashMap, String, boolean, and double. 222 */ 223 <T> JsonType<T> type(Class<T> cls); 224 225 /** 226 * Return the JsonType used to read and write json for the given type. 227 * <p> 228 * We can use {@link Types} to obtain common generic types for List, Set, Map, Array etc. 229 * 230 * <h3>Example</h3> 231 * <pre>{@code 232 * 233 * JsonType<List<String>> listOfStringType = jsonb.type(Types.listOf(String.class)) 234 * 235 * JsonType<List<Customer>> listOfCustomerType = jsonb.type(Types.listOf(Customer.class)) 236 * 237 * JsonType<Map<String,Integer>> adapter = jsonb.type(Types.mapOf(Integer.class)) 238 * 239 * }</pre> 240 * 241 * <h3>Using Object.class</h3> 242 * <p> 243 * We can use <code>type(Object.class)</code> when we don't know the specific type that is being 244 * written toJson or read fromJson. 245 * 246 * <h3>Object toJson()</h3> 247 * <pre>{@code 248 * 249 * Object any = ... 250 * 251 * String jsonContent = jsonb 252 * .type(Object.class) 253 * .toJson(any); 254 * 255 * // the same as 256 * String jsonContent = jsonb.toJson(any); 257 * 258 * }</pre> 259 * <p> 260 * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter 261 * is determined dynamically based on the type of the object value passed in. 262 * <p> 263 * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in 264 * the result are determined dynamically based on the json types being read and the resulting java types 265 * are ArrayList, LinkedHashMap, String, boolean, and double. 266 */ 267 <T> JsonType<T> type(Type type); 268 269 /** 270 * Return the JsonType for the given value using the class of the value being passed in. 271 * <p> 272 * This is a helper method that supports returning an inferred generic type. 273 * 274 * @param value The value of the given type 275 * @param <T> The inferred generic parameter type 276 * @return JsonType for the given value 277 */ 278 <T> JsonType<T> typeOf(Object value); 279 280 /** 281 * Return the JsonReader used to read the given json content. 282 */ 283 JsonReader reader(String json); 284 285 /** 286 * Return the JsonReader used to read the given json content in bytes. 287 */ 288 JsonReader reader(byte[] jsonBytes); 289 290 /** 291 * Return the JsonReader used to read the json content from the given reader. 292 */ 293 JsonReader reader(Reader reader); 294 295 /** 296 * Return the JsonReader used to read the json content from the given inputStream. 297 */ 298 JsonReader reader(InputStream inputStream); 299 300 /** 301 * Return the JsonWriter used to write json to the given writer. 302 */ 303 JsonWriter writer(Writer writer); 304 305 /** 306 * Return the JsonWriter used to write json to the given outputStream. 307 */ 308 JsonWriter writer(OutputStream outputStream); 309 310 /** 311 * Return the property names as PropertyNames. 312 * <p> 313 * Provides the option of optimising the writing of json for property names 314 * by having them already escaped and encoded rather than as plain strings. 315 */ 316 PropertyNames properties(String... names); 317 318 /** 319 * Return the JsonAdapter used to read and write json for the given class. 320 * <p> 321 * JsonAdapter is generally used by generated code and your application code 322 * is expected to use {@link Jsonb#type(Class)} and {@link JsonType} instead. 323 */ 324 <T> JsonAdapter<T> adapter(Class<T> cls); 325 326 /** 327 * Return the JsonAdapter used to read and write json for the given type. 328 * <p> 329 * JsonAdapter is generally used by generated code and your application code 330 * is expected to use {@link Jsonb#type(Type)} and {@link JsonType} instead. 331 */ 332 <T> JsonAdapter<T> adapter(Type type); 333 334 /** 335 * Raw JsonAdapter for raw json content. 336 */ 337 JsonAdapter<String> rawAdapter(); 338 339 /** 340 * Build the Jsonb instance adding JsonAdapter, Factory or AdapterBuilder. 341 */ 342 interface Builder { 343 344 /** 345 * Set to serialise null values or not. 346 * <p> 347 * Default is to not serialise nulls. 348 */ 349 Builder serializeNulls(boolean serializeNulls); 350 351 /** 352 * Set to serialise empty collections or not. 353 * <p> 354 * Default is to not serialise empty collections. 355 */ 356 Builder serializeEmpty(boolean serializeEmpty); 357 358 /** 359 * Set failOnUnknown to true such that an exception is thrown when unknown 360 * properties are read in the json content. 361 */ 362 Builder failOnUnknown(boolean failOnUnknown); 363 364 /** 365 * Set to true for BigDecimal and BigInteger to serialise as String values rather than number values. 366 */ 367 Builder mathTypesAsString(boolean mathTypesAsString); 368 369 /** 370 * Explicitly set the adapter to use. 371 * <p> 372 * When not set the JsonStreamAdapter is service loaded using {@link AdapterFactory} 373 * with a fallback default of using the builtin implementation. 374 * 375 * @param streamAdapter The underlying adapter to use when generating and parsing 376 */ 377 Builder adapter(JsonStreamAdapter streamAdapter); 378 379 /** 380 * Add a JsonAdapter to use for the given type. 381 */ 382 <T> Builder add(Type type, JsonAdapter<T> jsonAdapter); 383 384 /** 385 * Add a AdapterBuilder which provides a JsonAdapter to use for the given type. 386 */ 387 Builder add(Type type, AdapterBuilder builder); 388 389 /** 390 * Add a Component which can provide multiple JsonAdapters and or configuration. 391 */ 392 Builder add(Jsonb.Component component); 393 394 /** 395 * Add a JsonAdapter.Factory which provides JsonAdapters to use. 396 */ 397 Builder add(JsonAdapter.Factory factory); 398 399 /** 400 * Build and return the Jsonb instance with all the given adapters and factories registered. 401 */ 402 Jsonb build(); 403 } 404 405 /** 406 * Function to build a JsonAdapter that needs Jsonb. 407 */ 408 @FunctionalInterface 409 interface AdapterBuilder { 410 411 /** 412 * Create a JsonAdapter given the Jsonb instance. 413 */ 414 JsonAdapter<?> build(Jsonb jsonb); 415 } 416 417 /** 418 * Components register JsonAdapters Jsonb.Builder 419 */ 420 @FunctionalInterface 421 interface Component { 422 423 /** 424 * Register JsonAdapters with the Builder. 425 */ 426 void register(Builder builder); 427 } 428}