如何使用规范工具从内部地图中删除额外的键
How to remove extra keys from internal map using spec-tools
我正在尝试使用 clojure.spec 和 metosin/spec-tools 来验证和符合我的应用程序中的数据。在阅读了 spec-tools 文档后,我不清楚我应该如何使用 spec-tools.core/spec
包装我的规范,以便符合的数据没有额外的键(它适用于顶级地图但不适用于内部结构的地图).
一些有助于澄清问题的代码:
(ns prodimg.spec
(:require [clojure.spec.alpha :as s]
[spec-tools.core :as st]
[spec-tools.spec :as st.spec]))
(def ^:private not-blank? #(and (string? %)
(not (clojure.string/blank? %))))
(s/def :db/id integer?)
(s/def :model.image/id :db/id)
(s/def :model.image/type not-blank?)
(s/def :model.image/product-id :db/id)
(s/def :model.product/id :db/id)
(s/def :model.product/parent-id (s/nilable :db/id))
(s/def :model.product/name not-blank?)
(s/def :model.product/description string?)
(s/def :model.product/price (s/nilable decimal?))
; ----- request specs -----
; create product
(s/def :req.product.create/images (s/* (s/keys :req-un [:model.image/type])))
(s/def :req.product.create/children
(s/* (s/keys :req-un [:model.product/name :model.product/description]
:opt-un [:model.product/price])))
(s/def :req.product/create
(st/spec (s/keys :req-un [:model.product/name :model.product/description]
:opt-un [:model.product/price
:model.product/parent-id
:req.product.create/images
:req.product.create/children])))
现在假设我有以下想要的数据validate/conform:
(def data {:name "Product"
:description "Product description"
:price (bigdec "399.49")
:extra-key "something"
:images [{:type "PNG" :extra-key "something else"}])
(st/conform :req.product/create data st/strip-extra-keys-conforming)
; below is the result
; {:name "Product"
:description "Product description"
:price 399.49M
:images [{:type "PNG" :extra-key "something else"}]
我尝试更改 :req.product.create/images
声明以包含 st/spec
调用包装 s/*
形式或 s/keys
形式,或两者,但更改没有改变结果。
有什么办法可以解决这个问题吗?
奇怪,最新版本 [metosin/spec-tools "0.5.1"]
于 2017 年 10 月 31 日发布(所以在您的 post 之前),我唯一需要做的更改是按照 [=] 部分下文档中的示例进行操作=16=],这似乎是您已经尝试过的尝试之一:用 st/spec
包裹 s/keys
,如下所示:
改变
(s/def :req.product.create/images (s/* (s/keys :req-un [:model.image/type])))
到
(s/def :req.product.create/images (s/* (st/spec (s/keys :req-un [:model.image/type]))))
我得到了预期的输出:
(st/conform :req.product/create data st/strip-extra-keys-conforming)
=>
{:description "Product description",
:images [{:type "PNG"}],
:name "Product",
:price 399.49M}
我正在尝试使用 clojure.spec 和 metosin/spec-tools 来验证和符合我的应用程序中的数据。在阅读了 spec-tools 文档后,我不清楚我应该如何使用 spec-tools.core/spec
包装我的规范,以便符合的数据没有额外的键(它适用于顶级地图但不适用于内部结构的地图).
一些有助于澄清问题的代码:
(ns prodimg.spec
(:require [clojure.spec.alpha :as s]
[spec-tools.core :as st]
[spec-tools.spec :as st.spec]))
(def ^:private not-blank? #(and (string? %)
(not (clojure.string/blank? %))))
(s/def :db/id integer?)
(s/def :model.image/id :db/id)
(s/def :model.image/type not-blank?)
(s/def :model.image/product-id :db/id)
(s/def :model.product/id :db/id)
(s/def :model.product/parent-id (s/nilable :db/id))
(s/def :model.product/name not-blank?)
(s/def :model.product/description string?)
(s/def :model.product/price (s/nilable decimal?))
; ----- request specs -----
; create product
(s/def :req.product.create/images (s/* (s/keys :req-un [:model.image/type])))
(s/def :req.product.create/children
(s/* (s/keys :req-un [:model.product/name :model.product/description]
:opt-un [:model.product/price])))
(s/def :req.product/create
(st/spec (s/keys :req-un [:model.product/name :model.product/description]
:opt-un [:model.product/price
:model.product/parent-id
:req.product.create/images
:req.product.create/children])))
现在假设我有以下想要的数据validate/conform:
(def data {:name "Product"
:description "Product description"
:price (bigdec "399.49")
:extra-key "something"
:images [{:type "PNG" :extra-key "something else"}])
(st/conform :req.product/create data st/strip-extra-keys-conforming)
; below is the result
; {:name "Product"
:description "Product description"
:price 399.49M
:images [{:type "PNG" :extra-key "something else"}]
我尝试更改 :req.product.create/images
声明以包含 st/spec
调用包装 s/*
形式或 s/keys
形式,或两者,但更改没有改变结果。
有什么办法可以解决这个问题吗?
奇怪,最新版本 [metosin/spec-tools "0.5.1"]
于 2017 年 10 月 31 日发布(所以在您的 post 之前),我唯一需要做的更改是按照 [=] 部分下文档中的示例进行操作=16=],这似乎是您已经尝试过的尝试之一:用 st/spec
包裹 s/keys
,如下所示:
改变
(s/def :req.product.create/images (s/* (s/keys :req-un [:model.image/type])))
到
(s/def :req.product.create/images (s/* (st/spec (s/keys :req-un [:model.image/type]))))
我得到了预期的输出:
(st/conform :req.product/create data st/strip-extra-keys-conforming)
=>
{:description "Product description",
:images [{:type "PNG"}],
:name "Product",
:price 399.49M}