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}