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