001package io.avaje.jsonb;
002
003import java.lang.annotation.ElementType;
004import java.lang.annotation.Repeatable;
005import java.lang.annotation.Retention;
006import java.lang.annotation.Target;
007
008import static java.lang.annotation.RetentionPolicy.CLASS;
009import static java.lang.annotation.RetentionPolicy.RUNTIME;
010
011/**
012 * Marks a type for JSON support.
013 */
014@Retention(CLASS)
015@Target(ElementType.TYPE)
016public @interface Json {
017
018  /**
019   * Specify the naming convention to use for the properties on this type.
020   */
021  Naming naming() default Naming.Match;
022
023  /**
024   * When {@code @Json.SubType} is used this specifies the name of the property
025   * field that holds the type name (discriminator value).
026   * <p>
027   * This defaults to {@code @type} when unspecified.
028   */
029  String typeProperty() default "";
030
031  /**
032   * Specify types to generate JsonAdapters for.
033   * <p>
034   * These types are typically in an external project / dependency or otherwise
035   * types that we can't or don't want to explicitly annotate with {@code @Json}.
036   */
037  @Retention(CLASS)
038  @Target({ElementType.TYPE, ElementType.PACKAGE})
039  @interface Import {
040
041    /**
042     * Specify types to generate Json Adapters for.
043     */
044    Class<?>[] value();
045  }
046
047  /**
048   * Override the json property name.
049   */
050  @Retention(CLASS)
051  @Target({ElementType.FIELD})
052  @interface Property {
053
054    /**
055     * Specify the name for this property.
056     */
057    String value();
058  }
059
060  /**
061   * Exclude the property from serialization, deserialization or both.
062   * <p>
063   * We can explicitly use {@code deserialize=true} to include the property in
064   * deserialization but not serialization. For example, we might do this on
065   * a property that represents a secret like a password.
066   * <p>
067   * We can explicitly use {@code serialize=true} to include the property in
068   * serialization but not deserialization.
069   */
070  @Retention(CLASS)
071  @Target({ElementType.FIELD})
072  @interface Ignore {
073
074    /**
075     * Set this explicitly to true to include in serialization.
076     */
077    boolean serialize() default false;
078
079    /**
080     * Set this explicitly to true to include in deserialization.
081     */
082    boolean deserialize() default false;
083  }
084
085  /**
086   * Annotate a {@code Map<String,Object>} field to hold unmapped json properties.
087   * <p>
088   * When reading unknown properties from json content these are read and put into
089   * this map. When writing json this map is included back into the content.
090   *
091   * <pre>{@code
092   *
093   *   @Json.Unmapped
094   *   Map<String, Object> unmapped;
095   *
096   * }</pre>
097   */
098  @Retention(CLASS)
099  @Target({ElementType.FIELD})
100  @interface Unmapped {
101
102  }
103
104  /**
105   * Mark a method on an Enum that provides the json value.
106   * <p>
107   * If the method returns an int type then it is mapped to json int, otherwise it is
108   * treated as providing json string values.
109   *
110   * <pre>{@code
111   *
112   *   public enum MyEnum {
113   *
114   *     ONE("one value"),
115   *     TWO("two value");
116   *
117   *     final String val;
118   *     MyEnum(String val) {
119   *       this.val = val;
120   *     }
121   *
122   *     // method provides the values used to serialise to and from json
123   *
124   *     @Json.Value
125   *     public String value() {
126   *       return val;
127   *     }
128   *   }
129   *
130   * }</pre>
131   */
132  @Retention(RUNTIME)
133  @Target({ElementType.METHOD})
134  @interface Value {
135  }
136
137  /**
138   * Specify the subtypes that a given type can be represented as.
139   * <p>
140   * This is used on an interface type, abstract type or type with inheritance
141   * to indicate all the concrete subtypes that can represent the type.
142   * <p>
143   * In the example below the abstract Vehicle type has 2 concrete subtypes
144   * of Car and Truck that can represent the type.
145   *
146   * <pre>{@code
147   *
148   *   @Json
149   *   @Json.SubType(type = Car.class)
150   *   @Json.SubType(type = Truck.class, name = "TRUCK")
151   *   public abstract class Vehicle {
152   *    ...
153   *
154   * }</pre>
155   */
156  @Retention(CLASS)
157  @Target({ElementType.TYPE})
158  @Repeatable(SubTypes.class)
159  @interface SubType {
160
161    /**
162     * The concrete type that extends or implements the base type.
163     */
164    Class<?> type();
165
166    /**
167     * The name or "discriminator value" that is used to identify the type.
168     * <p>
169     * When unspecified this is the short name of the class.
170     */
171    String name() default "";
172  }
173
174  /**
175   * Container of all the concrete SubType's that an interface type or abstract
176   * type can be represented as.
177   */
178  @Retention(CLASS)
179  @Target({ElementType.TYPE})
180  @interface SubTypes {
181
182    SubType[] value();
183  }
184
185  /**
186   * Marks a String field as containing raw JSON content.
187   */
188  @Retention(CLASS)
189  @Target({ElementType.FIELD})
190  @interface Raw {
191
192  }
193
194  /**
195   * The naming convention that we can use for a given type.
196   */
197  enum Naming {
198    Match,
199    LowerHyphen,
200    LowerUnderscore,
201    LowerSpace,
202    UpperCamel,
203    UpperHyphen,
204    UpperUnderscore,
205    UpperSpace
206  }
207
208}