xref: /aosp_15_r20/external/json-schema-validator/doc/specversion.md (revision 78c4dd6aa35290980cdcd1623a7e337e8d021c7c)
1The library supports V4, V6, V7, V2019-09 and V2020-12 JSON schema specifications. By default, V4 is used for backward compatibility.
2
3### For Users
4
5#### To create a draft V4 JsonSchemaFactory
6
7```java
8ObjectMapper mapper = new ObjectMapper();
9JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4)).objectMapper(mapper).build();
10```
11or with default configuration
12```java
13JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4));
14```
15
16Please avoid using default `getInstance()`, which, internally, defaults to the `SpecVersion.VersionFlag.V4` as the parameter. This is deprecated.
17
18#### To create a draft V6 JsonSchemaFactory
19
20```java
21ObjectMapper mapper = new ObjectMapper();
22JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V6)).objectMapper(mapper).build();
23```
24or with default configuration
25```java
26JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V6));
27```
28
29#### To create a draft V7 JsonSchemaFactory
30
31```java
32ObjectMapper mapper = new ObjectMapper();
33JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7)).objectMapper(mapper).build();
34```
35or with default configuration
36```java
37JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7));
38```
39
40#### To create a draft 2019-09 JsonSchemaFactory
41
42```java
43ObjectMapper mapper = new ObjectMapper();
44JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909)).objectMapper(mapper).build();
45```
46or with default configuration
47```java
48JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909));
49```
50
51#### To create a draft 2020-12 JsonSchemaFactory
52
53```java
54ObjectMapper mapper = new ObjectMapper();
55JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
56```
57or with default configuration
58```java
59JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012));
60```
61
62#### To create a JsonSchemaFactory, automatically detecting schema version
63
64```java
65ObjectMapper mapper = new ObjectMapper();
66JsonNode jsonNode = mapper.readTree(/* schema / schema input steam etc. */);
67JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersionDetector.detect(jsonNode))).objectMapper(mapper).build();
68```
69or with default configuration
70```java
71ObjectMapper mapper = new ObjectMapper();
72JsonNode jsonNode = mapper.readTree(/* schema / schema input steam etc. */);
73JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(jsonNode));
74```
75
76### For Developers
77
78#### SpecVersion
79
80A new class `SpecVersion` has been introduced to indicate which version of the specification is used when creating the `JsonSchemaFactory`. The `SpecVersion` has an enum and two methods to convert a long to an `EnumSet` or a set of `VersionFlags` to a long value.
81
82```java
83public enum VersionFlag {
84
85    V4(1<<0),
86    V6(1<<1),
87    V7(1<<2),
88    V201909(1<<3),
89    V202012(1<<4);
90
91```
92
93In the long value, we are using 5 bits now as we are supporting 5 versions at the moment.
94
95V4 -> 00001 -> 1
96V6 -> 00010 -> 2
97V7 -> 00100 -> 4
98V201909 -> 01000 -> 8
99V202012 -> 10000 --> 16
100
101If we have a new version added, it should be
102
103V202209 -> 100000 -> 32
104
105#### ValidatorTypeCode
106
107A new field versionCode is added to indicate which version the validator is supported.
108
109For most of the validators, the version code should be 31, which is 11111. This means the validator will be loaded for every version of the specification.
110
111For example.
112
113```java
114MAXIMUM("maximum", "1011", new MessageFormat("{0}: must have a maximum value of {1}"), MaximumValidator.class, 31),
115```
116
117Since if-then-else was introduced in the V7, it only works for V7, V2019-09 and V2020-12
118
119```java
120IF_THEN_ELSE("if", "1037", null, IfValidator.class, 28),  // V7|V201909|V202012 11100
121```
122
123For exclusiveMaximum, it was introduced from V6
124
125```java
126EXCLUSIVE_MAXIMUM("exclusiveMaximum", "1038", new MessageFormat("{0}: must have a exclusive maximum value of {1}"), ExclusiveMaximumValidator.class, 30),  // V6|V7|V201909|V202012
127```
128
129The getNonFormatKeywords method is updated to accept a SpecVersion.VersionFlag so that only the keywords supported by the specification will be loaded.
130
131```java
132public static List<ValidatorTypeCode> getNonFormatKeywords(SpecVersion.VersionFlag versionFlag) {
133    final List<ValidatorTypeCode> result = new ArrayList<ValidatorTypeCode>();
134    for (ValidatorTypeCode keyword: values()) {
135        if (!FORMAT.equals(keyword) && specVersion.getVersionFlags(keyword.versionCode).contains(versionFlag)) {
136            result.add(keyword);
137        }
138    }
139    return result;
140}
141```
142
143#### JsonMetaSchema
144
145We have created four different static classes V4, V6, V7, V201909 and V202012 to build different `JsonMetaSchema` instances.
146
147For the BUILDIN_FORMATS, there is a common section, and each static class has its version-specific BUILDIN_FORMATS section.
148
149#### JsonSchemaFactory
150
151The getInstance supports a parameter `SpecVersion.VersionFlag` to get the right instance of the `JsonMetaShema` to create the factory. If there is no parameter, then V4 is used by default.
152
153```java
154@Deprecated
155public static JsonSchemaFactory getInstance() {
156    return getInstance(SpecVersion.VersionFlag.V4);
157}
158
159public static JsonSchemaFactory getInstance(SpecVersion.VersionFlag versionFlag) {
160    JsonSchemaVersion jsonSchemaVersion = checkVersion(versionFlag);
161    JsonMetaSchema metaSchema = jsonSchemaVersion.getInstance();
162    return builder()
163            .defaultMetaSchemaIri(metaSchema.getIri())
164            .metaSchema(metaSchema)
165            .build();
166}
167```
168
169#### SpecVersionDetector
170
171This class detects schema version based on the schema tag.
172
173```java
174private static final String SCHEMA_TAG = "$schema";
175
176public static SpecVersion.VersionFlag detect(JsonNode jsonNode) {
177    if (!jsonNode.has(SCHEMA_TAG))
178        throw new JsonSchemaException("Schema tag not present");
179
180    final boolean forceHttps = true;
181    final boolean removeEmptyFragmentSuffix = true;
182
183    String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(jsonNode.get(SCHEMA_TAG).asText(), forceHttps, removeEmptyFragmentSuffix);
184    if (schemaUri.equals(JsonMetaSchema.getV4().getIri()))
185        return SpecVersion.VersionFlag.V4;
186    else if (schemaUri.equals(JsonMetaSchema.getV6().getIri()))
187        return SpecVersion.VersionFlag.V6;
188    else if (schemaUri.equals(JsonMetaSchema.getV7().getIri()))
189        return SpecVersion.VersionFlag.V7;
190    else if (schemaUri.equals(JsonMetaSchema.getV201909().getIri()))
191        return SpecVersion.VersionFlag.V201909;
192    else if (schemaUri.equals(JsonMetaSchema.getV202012().getIri()))
193        return SpecVersion.VersionFlag.V202012;
194    else
195        throw new JsonSchemaException("Unrecognizable schema");
196}
197```
198
199### For Testers
200
201In the test resource folder, we have created and copied all draft version's test suite. They are located in draft4, draft6, draft7, draft2019-09 and draft2020-12 folders.
202
203The existing JsonSchemaTest has been renamed to V4JsonSchemaTest, and the following test classes are added.
204
205```
206V6JsonSchemaTest
207V7JsonSchemaTest
208V201909JsonSchemaTest
209V202012JsonSchemaTest
210```
211
212These new test classes are not completed yet, and only some sample test cases are added.
213
214