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}