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