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