Last active
February 10, 2019 19:38
-
-
Save ikitommi/68f662a399a90e8a70308ffcd4b3e752 to your computer and use it in GitHub Desktop.
clojure.spec JSON coercion + dropping extra keys for safety
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; [metosin/spec-tools "0.8.2"] | |
;; from https://github.com/metosin/reitit/blob/master/modules/reitit-spec/src/reitit/coercion/spec.cljc | |
(require '[clojure.spec.alpha :as s]) | |
(require '[spec-tools.core :as st]) | |
;; | |
;; define some specs | |
;; | |
(s/def ::DATE inst?) | |
(s/def ::zip int?) | |
(s/def ::country keyword?) | |
(s/def ::address (s/keys :req-un [::zip ::country])) | |
(s/def ::name string?) | |
(s/def ::user (s/keys :req-un [::name ::address])) | |
;; | |
;; let's coerce the JSON payload at runtime | |
;; | |
;; all good | |
(st/coerce | |
::user | |
{:name "pirjo" | |
:address {:zip 33800 | |
:country "fi"}} | |
st/json-transformer) | |
; {:name "pirjo" | |
; :address {:zip 33800 | |
; :country :fi} | |
;; but, it doesn't strip away the extra keys AND all qualified keys are validated, | |
;; despite not being part of the s/keys spec :( | |
(st/coerce | |
::user | |
{:name "pirjo" | |
::DATE "2007-11-20T22:19:17+02:00" | |
:address {:zip 33800 | |
::DATE "2007-11-20T22:19:17+02:00" | |
:country "fi"}} | |
st/json-transformer) | |
; {:name "pirjo", | |
; :user/DATE #inst"2007-11-20T20:19:17.000-00:00", | |
; :address {:zip 33800, | |
; :user/DATE #inst"2007-11-20T20:19:17.000-00:00", | |
; :country :fi}} | |
;; | |
;; let's create a json transformer, that also strip away the extra map keys | |
;; | |
(require '[spec-tools.transform :as stt]) | |
(def extra-keys-stripping-json-transformer | |
(st/type-transformer | |
{:name :json | |
:decoders (merge | |
stt/json-type-decoders | |
stt/strip-extra-keys-type-decoders) | |
:encoders stt/json-type-encoders | |
:default-encoder stt/any->any})) | |
;; all good. | |
(st/coerce | |
::user | |
{:name "pirjo" | |
::DATE "2007-11-20T22:19:17+02:00" | |
:address {:zip 33800 | |
::DATE "2007-11-20T22:19:17+02:00" | |
:country "fi"}} | |
extra-keys-stripping-json-transformer) | |
; {{:address {:zip 33800, :country :fi}, :name "pirjo"} | |
; :address {:zip 33800 | |
; :country :fi}} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment