Skip to content

Commit ea023e5

Browse files
authored
Merge pull request #281 from RucaHQ/support-multispec-json-schema-transforms
Support transform of multi-spec to JSON Schema
2 parents ec02b0a + ba12bd5 commit ea023e5

File tree

4 files changed

+35
-0
lines changed

4 files changed

+35
-0
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
* Support transforming schema to JSON Schema. PR [#281](https://github.com/metosin/spec-tools/pull/281)
4+
15
# 0.10.6 (2023-08-28)
26

37
* Deprecate `spec-tools.openapi/openapi-spec`

src/spec_tools/json_schema.cljc

+3
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@
228228
(defmethod accept-spec 'spec-tools.core/merge [_ spec children options]
229229
(accept-merge children spec options))
230230

231+
(defmethod accept-spec 'clojure.spec.alpha/multi-spec [_ _ children _]
232+
{:anyOf children})
233+
231234
(defmethod accept-spec 'clojure.spec.alpha/every [_ spec children options]
232235
(let [form (impl/extract-form spec)
233236
{:keys [type]} (parse/parse-spec form)]

src/spec_tools/visitor.cljc

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@
7777
(defmethod visit-spec 'spec-tools.core/merge [spec accept options]
7878
(visit-merge spec accept options))
7979

80+
(defmethod visit-spec 'clojure.spec.alpha/multi-spec [spec accept options]
81+
(let [methods-specs (->> (impl/extract-form spec)
82+
(parse/get-multi-spec-sub-specs)
83+
(into {}))]
84+
(accept 'clojure.spec.alpha/multi-spec spec (mapv #(visit (val %) accept options) methods-specs) options)))
85+
8086
(defmethod visit-spec 'clojure.spec.alpha/every [spec accept options]
8187
(let [[_ inner-spec] (impl/extract-form spec)]
8288
(accept 'clojure.spec.alpha/every spec [(visit inner-spec accept options)] options)))

test/cljc/spec_tools/json_schema_test.cljc

+22
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@
2727
(s/def ::keys-no-req (s/keys :opt [::e]
2828
:opt-un [::e]))
2929

30+
(defmulti event-payload :action)
31+
32+
(s/def :event.payload.add/action #{:add})
33+
(s/def :event.payload.add/payload int?)
34+
35+
(defmethod event-payload :add
36+
[_]
37+
(s/keys :req-un [:event.payload.add/action :event.payload.add/payload]))
38+
39+
(s/def :event.payload.result/action #{:result})
40+
(s/def :event.payload.result/payload nil?)
41+
42+
(defmethod event-payload :result
43+
[_]
44+
(s/keys :req-un [:event.payload.result/action]
45+
:opt-un [:event.payload.result/payload]))
46+
3047
(deftest simple-spec-test
3148
(testing "primitive predicates"
3249
;; You're intented to call jsc/to-json with a registered spec, but to avoid
@@ -99,6 +116,11 @@
99116
:properties {"spec-tools.json-schema-test/integer" {:type "integer"}
100117
"spec-tools.json-schema-test/string" {:type "string"}}
101118
:required ["spec-tools.json-schema-test/integer" "spec-tools.json-schema-test/string"]}))
119+
(is (= (jsc/transform (s/multi-spec event-payload :action))
120+
{:anyOf [{:type "object" :properties {"action" {:enum [:result]} "payload" {:type "null"}} :required ["action"]}
121+
{:type "object"
122+
:properties {"action" {:enum [:add]} "payload" {:type "integer" :format "int64"}}
123+
:required ["action" "payload"]}]}))
102124
(is (= (jsc/transform (s/every integer?)) {:type "array" :items {:type "integer"}}))
103125
(is (= (jsc/transform (s/every-kv string? integer?))
104126
{:type "object" :additionalProperties {:type "integer"}}))

0 commit comments

Comments
 (0)