Skip to content

Instantly share code, notes, and snippets.

@ikitommi
Last active February 10, 2019 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ikitommi/68f662a399a90e8a70308ffcd4b3e752 to your computer and use it in GitHub Desktop.
Save ikitommi/68f662a399a90e8a70308ffcd4b3e752 to your computer and use it in GitHub Desktop.
clojure.spec JSON coercion + dropping extra keys for safety
;; [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