如何使用spec-tools从内部地图中删除额外的键

时间:2017-12-14 22:32:56

标签: clojure clojure.spec

我尝试使用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])))

现在假设我有以下要验证/符合的数据:

(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表单,或两者,但这些更改并非如此改变结果。

我有什么想法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

奇怪,最新版本s/keys已于2017年10月31日发布(所以在发布之前),我唯一需要做的改变就是按照Map conforming部分下的文档中的示例进行操作似乎是您尝试过的尝试之一:将st/spec(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}

我得到了预期的输出:

view some_process(base_owns_data &b)
{
    auto working_view = b.base_owns_data::get_view();
    // Do a bunch of things to filter the view
    return working_view;
}