001package io.avaje.jsonb;
002
003import io.avaje.jsonb.core.DefaultBootstrap;
004import io.avaje.jsonb.spi.Bootstrap;
005import io.avaje.jsonb.spi.PropertyNames;
006
007import java.io.InputStream;
008import java.io.OutputStream;
009import java.io.Reader;
010import java.io.Writer;
011import java.lang.reflect.Type;
012import java.util.Iterator;
013import java.util.ServiceLoader;
014
015/**
016 * Provides access to json adapters by type.
017 *
018 * <h4>Initialise with defaults</h3>
019 *
020 * <pre>{@code
021 *   Jsonb jsonb = Jsonb.newBuilder().build();
022 * }</pre>
023 *
024 * <h4>Initialise with some configuration</h3>
025 *
026 * <pre>{@code
027 *   Jsonb jsonb = Jsonb.newBuilder()
028 *     .serializeNulls(true)
029 *     .serializeEmpty(true)
030 *     .failOnUnknown(true)
031 *     .build();
032 * }</pre>
033 *
034 * <h4>fromJson</h4>
035 * <p>
036 * Read json content from: String, byte[], Reader, InputStream, JsonReader
037 * </p>
038 * <pre>{@code
039 *
040 *  JsonType<Customer> customerType = jsonb.type(Customer.class);
041 *
042 *  Customer customer = customerType.fromJson(content);
043 *
044 * }</pre>
045 *
046 * <h4>toJson</h4>
047 * <p>
048 * Write json content to: String, byte[], Writer, OutputStream, JsonWriter
049 * </p>
050 * <pre>{@code
051 *
052 *  JsonType<Customer> customerType = jsonb.type(Customer.class);
053 *
054 *  String asJson = customerType.toJson(customer);
055 *
056 * }</pre>
057 */
058public interface Jsonb {
059
060  /**
061   * Create and return a new Jsonb.Builder to configure before building the Jsonb instance.
062   * <p>
063   * We can register JsonAdapter's to use for specific types before building and returning
064   * the Jsonb instance to use.
065   * <p>
066   * Note that JsonAdapter's that are generated are automatically registered via service
067   * loading so there is no need to explicitly register those generated JsonAdapters.
068   *
069   * <pre>{@code
070   *
071   *   Jsonb jsonb = Jsonb.newBuilder()
072   *     .serializeNulls(true)
073   *     .serializeEmpty(true)
074   *     .failOnUnknown(true)
075   *     .build();
076   *
077   * }</pre>
078   */
079  static Builder newBuilder() {
080    Iterator<Bootstrap> bootstrapService = ServiceLoader.load(Bootstrap.class).iterator();
081    if (bootstrapService.hasNext()) {
082      return bootstrapService.next().newBuilder();
083    }
084    return DefaultBootstrap.newBuilder();
085  }
086
087  /**
088   * Return the JsonType used to read and write json for the given class.
089   *
090   * <h3>Using Object.class</h3>
091   * <p>
092   * We can use <code>type(Object.class)</code> when we don't know the specific type that is being
093   * written toJson or read fromJson.
094   * <p>
095   * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter
096   * is determined dynamically based on the type of the object value passed in.
097   * <p>
098   * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in
099   * the result are determined dynamically based on the JSON types being read and the resulting java types
100   * are ArrayList, LinkedHashMap, String, boolean, and double.
101   */
102  <T> JsonType<T> type(Class<T> cls);
103
104  /**
105   * Return the JsonType used to read and write json for the given type.
106   *
107   * <h3>Using Object.class</h3>
108   * <p>
109   * We can use <code>type(Object.class)</code> when we don't know the specific type that is being
110   * written toJson or read fromJson.
111   * <p>
112   * When using <code>Object.class</code> and writing <code>toJson()</code> then the underlying JsonAdapter
113   * is determined dynamically based on the type of the object value passed in.
114   * <p>
115   * When using <code>Object.class</code> and reading <code>fromJson()</code> then the java types used in
116   * the result are determined dynamically based on the JSON types being read and the resulting java types
117   * are ArrayList, LinkedHashMap, String, boolean, and double.
118   */
119  <T> JsonType<T> type(Type type);
120
121  /**
122   * Return the JsonType for the given value using the values class.
123   * <p>
124   * This is a helper method that supports returning an inferred generic type.
125   *
126   * @param value The value of the given type
127   * @param <T>   The inferred generic parameter type
128   * @return JsonType for the given value
129   */
130  <T> JsonType<T> typeOf(Object value);
131
132  /**
133   * Return the JsonAdapter used to read and write json for the given class.
134   */
135  <T> JsonAdapter<T> adapter(Class<T> cls);
136
137  /**
138   * Return the JsonAdapter used to read and write json for the given type.
139   */
140  <T> JsonAdapter<T> adapter(Type type);
141
142  /**
143   * Return the JsonReader used to read the given json content.
144   */
145  JsonReader reader(String json);
146
147  /**
148   * Return the JsonReader used to read the given json content in bytes.
149   */
150  JsonReader reader(byte[] jsonBytes);
151
152  /**
153   * Return the JsonReader used to read the json content from the given reader.
154   */
155  JsonReader reader(Reader reader);
156
157  /**
158   * Return the JsonReader used to read the json content from the given inputStream.
159   */
160  JsonReader reader(InputStream inputStream);
161
162  /**
163   * Return the JsonWriter used to write json to the given writer.
164   */
165  JsonWriter writer(Writer writer);
166
167  /**
168   * Return the JsonWriter used to write json to the given outputStream.
169   */
170  JsonWriter writer(OutputStream outputStream);
171
172  /**
173   * Return the property names as PropertyNames.
174   * <p>
175   * Provides the option of optimising the writing of json for property names
176   * by having them already escaped and encoded rather than as plain strings.
177   */
178  PropertyNames properties(String... names);
179
180  /**
181   * Build the Jsonb instance adding JsonAdapter, Factory or AdapterBuilder.
182   */
183  interface Builder {
184
185    /**
186     * Set to serialise null values or not.
187     * <p>
188     * Default is to not serialise nulls.
189     */
190    Builder serializeNulls(boolean serializeNulls);
191
192    /**
193     * Set to serialise empty collections or not.
194     * <p>
195     * Default is to not serialise empty collections.
196     */
197    Builder serializeEmpty(boolean serializeEmpty);
198
199    /**
200     * Set failOnUnknown to true such that an exception is thrown when unknown
201     * properties are read in the json content.
202     */
203    Builder failOnUnknown(boolean failOnUnknown);
204
205    /**
206     * Set to true for BigDecimal and BigInteger to serialise as String values rather than number values.
207     */
208    Builder mathTypesAsString(boolean mathTypesAsString);
209
210    /**
211     * Add a JsonAdapter to use for the given type.
212     */
213    <T> Builder add(Type type, JsonAdapter<T> jsonAdapter);
214
215    /**
216     * Add a AdapterBuilder which provides a JsonAdapter to use for the given type.
217     */
218    Builder add(Type type, AdapterBuilder builder);
219
220    /**
221     * Add a Component which can provide multiple JsonAdapters and or configuration.
222     */
223    Builder add(Jsonb.Component component);
224
225    /**
226     * Add a JsonAdapter.Factory which provides JsonAdapters to use.
227     */
228    Builder add(JsonAdapter.Factory factory);
229
230    /**
231     * Build and return the Jsonb instance with all the given adapters and factories registered.
232     */
233    Jsonb build();
234  }
235
236  /**
237   * Function to build a JsonAdapter that needs Jsonb.
238   */
239  @FunctionalInterface
240  interface AdapterBuilder {
241
242    /**
243     * Create a JsonAdapter given the Jsonb instance.
244     */
245    JsonAdapter<?> build(Jsonb jsonb);
246  }
247
248  /**
249   * Components register JsonAdapters Jsonb.Builder
250   */
251  @FunctionalInterface
252  interface Component {
253
254    /**
255     * Register JsonAdapters with the Builder.
256     */
257    void register(Builder builder);
258  }
259}