Skip to content

Commit f2f5ce2

Browse files
authored
Merge pull request #9 from jurgiskg/default-classpath-resolution-scope
Allow relative file resolution in $ref fields
2 parents c62284e + bfb5026 commit f2f5ce2

File tree

6 files changed

+95
-29
lines changed

6 files changed

+95
-29
lines changed

src/json_schema/core.clj

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,42 @@
2525
(JSONObject. ^JSONTokener json-tokener)))
2626
(throw (ex-info "Unsupported JSON input" {:input input}))))
2727

28-
(defn- is-schema-input-valid? [input]
29-
(or (map? input)
30-
(and (string? input)
31-
(= \{ (first input)))))
28+
(defn- assert-schema-input-valid! [input]
29+
(let [is-input-valid? (or (map? input)
30+
(and (string? input)
31+
(= \{ (first input))))]
32+
(when-not is-input-valid?
33+
(throw (ex-info "Unsupported Schema input" {:input input})))))
3234

3335
(defn ^JSONObject prepare-schema*
34-
"Prepares JSON Schema based on input string or map.
35-
You can pass optional parameter :classpath-aware, in case you want to
36-
refer to relative file schemas via classpath in $ref fields."
37-
[input & params]
38-
(when-not (is-schema-input-valid? input)
39-
(throw (ex-info "Unsupported Schema input" {:input input})))
40-
(if-not (some #{:classpath-aware} params)
41-
(SchemaLoader/load (JSONObject. (prepare-tokener input)))
42-
(let [schema-loader (-> (SchemaLoader/builder)
43-
(.schemaClient (SchemaClient/classPathAwareClient))
44-
(.schemaJson (JSONObject. (prepare-tokener input)))
45-
(.build))]
46-
(.build (.load schema-loader)))))
36+
"Prepares JSON Schema based on input string or map. An optional parameter map
37+
can be supplied to refer to relative file schemas via classpath in $ref fields.
38+
39+
Setting :classpath-aware? to true enables absolute classpath resolution.
40+
(prepare-schema* input {:classpath-aware? true})
41+
42+
Setting :default-resolution-scope enables relative classpath resolution.
43+
Make sure to not use HTTP URIs in schema $id fields, as this
44+
will cause it to resort to default $ref resolution via HTTP.
45+
(prepare-schema* input {:classpath-aware? true
46+
:default-resolution-scope \"classpath://schemas/\"})"
47+
([input]
48+
(assert-schema-input-valid! input)
49+
(SchemaLoader/load (JSONObject. (prepare-tokener input))))
50+
([input params]
51+
(assert-schema-input-valid! input)
52+
(if-not (:classpath-aware? params)
53+
(prepare-schema* input)
54+
(let [resolution-scope (:default-resolution-scope params)
55+
set-resolution-scope (fn [client] (if resolution-scope
56+
(.resolutionScope client resolution-scope)
57+
client))
58+
schema-loader (-> (SchemaLoader/builder)
59+
(.schemaClient (SchemaClient/classPathAwareClient))
60+
(set-resolution-scope)
61+
(.schemaJson (JSONObject. (prepare-tokener input)))
62+
(.build))]
63+
(.build (.load schema-loader))))))
4764

4865
(def ^JSONObject prepare-schema (memoize prepare-schema*))
4966

test/json_schema/core_test.clj

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,34 @@
130130
(json/validate schema json-edn-invalid)))))))
131131

132132
(deftest classpath-ref-resolution
133-
(testing "JSON Schema with classpath ref loading"
134-
(let [schema-input (-> "person.json" io/resource slurp)
135-
schema (json/prepare-schema schema-input :classpath-aware)
136-
valid-input {:address {:street_address "Penguin Avenue 15"
133+
(testing "JSON Schema validation with classpath ref resolution"
134+
(let [valid-input {:address {:street_address "Penguin Avenue 15"
137135
:city "Vilnius"}}
138136
invalid-input {:address "Penguin Avenue 15, Vilnius"}]
139137

140-
(testing "valid EDN input for referred field via classpath VALIDATES"
141-
(is (= valid-input (json/validate schema valid-input))))
138+
(testing "Absolute classpath refs"
139+
(let [schema-input (-> "ref/absolute/person.json" io/resource slurp)
140+
schema (json/prepare-schema schema-input {:classpath-aware? true})]
142141

143-
(testing "invalid EDN input for referred field via classpath FAILS"
144-
(is (thrown-with-msg?
145-
Exception
146-
#"JSON Validation error"
147-
(json/validate schema invalid-input)))))))
142+
(testing "valid EDN input for absolute classpath ref VALIDATES"
143+
(is (= valid-input (json/validate schema valid-input))))
144+
145+
(testing "invalid EDN input for absolute classpath ref FAILS"
146+
(is (thrown-with-msg?
147+
Exception
148+
#"JSON Validation error"
149+
(json/validate schema invalid-input))))))
150+
151+
(testing "Relative classpath refs"
152+
(let [schema-input (-> "ref/relative/person.json" io/resource slurp)
153+
schema (json/prepare-schema schema-input {:classpath-aware? true
154+
:default-resolution-scope "classpath://ref/relative/"})]
155+
156+
(testing "valid EDN input for relative classpath ref VALIDATES"
157+
(is (= valid-input (json/validate schema valid-input))))
158+
159+
(testing "valid EDN input for relative classpath ref FAILS"
160+
(is (thrown-with-msg?
161+
Exception
162+
#"JSON Validation error"
163+
(json/validate schema invalid-input)))))))))
File renamed without changes.

test/resources/person.json renamed to test/resources/ref/absolute/person.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "object",
66
"properties": {
77
"address": {
8-
"$ref": "classpath://definitions.json#/definitions/address"
8+
"$ref": "classpath://ref/absolute/definitions.json#/definitions/address"
99
}
1010
},
1111
"required": ["address"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$id": "Definitions",
3+
"$schema": "http://json-schema.org/draft-07/schema#",
4+
"definitions": {
5+
"address": {
6+
"type": "object",
7+
"properties": {
8+
"street_address": {
9+
"type": "string"
10+
},
11+
"city": {
12+
"type": "string"
13+
}
14+
},
15+
"required": [
16+
"street_address",
17+
"city"
18+
]
19+
}
20+
}
21+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$id": "Person",
3+
"$schema": "http://json-schema.org/draft-07/schema#",
4+
"title": "Person",
5+
"type": "object",
6+
"properties": {
7+
"address": {
8+
"$ref": "definitions.json#/definitions/address"
9+
}
10+
},
11+
"required": ["address"]
12+
}

0 commit comments

Comments
 (0)