使用 Spec 验证已知和未知键值的映射
Validate map of known and unknown key-values with Spec
我想创建一个 clojure 规范来验证由 reitit.ring.middleware.multipart
中间件创建的 http 请求的 :multipart
参数。
多部分表单数据必须包含特定参数,这些参数可以使用 s/keys
和任意数量的具有任意参数名称的文件进行验证。
要验证的地图如下所示:
{:visualisation "vis"
:file-xy {:filename "foo.png",
:content-type "image/png",
:tempfile "C:\Temp\ring-multipart-123.tmp",
:size 295281}
:file-abc {:filename "bar.png",
:content-type "image/png",
:tempfile "C:\Temp\ring-multipart-456.tmp",
:size 42}}
我可以像这样使用 reitit.ring.middleware.multipart/temp-file-part
规范验证文件:
(s/def :multipart/files (s/map-of :multipart/param multipart/temp-file-part))
综合起来,我想出了一个通过的规范,但它允许所有未知参数是文件或字符串:
(s/def :multipart/param keyword?)
(s/def :multipart/visualisation string?)
(s/def :multipart/items (s/map-of :multipart/param (s/or :file multipart/temp-file-part :visualisation string?)))
(s/def :visualisation/files (s/and (s/keys :req-un [:multipart/visualisation])
:multipart/items))
如何为具有特定键的映射定义规范,并为其他键定义值验证器?
您可以添加谓词函数以确保只有一个映射值是字符串:
(s/def :visualisation/files
(s/and (s/keys :req-un [:multipart/visualisation])
#(= 1 (count (filter string? (vals %))))
:multipart/items))
(s/conform :visualisation/files
{:visualisation "vis"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
(s/conform :visualisation/files
{:visualisation "vis"
:file-abc "not valid"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
但是如果您使用 conform
的输出,包罗万象的 s/or
规范将产生冗余标签。
另一种选择是使用两个规范检查:
(def data
{:visualisation "vis"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
(s/conform (s/keys :req-un [:multipart/visualisation])
data)
(s/conform (s/map-of :multipart/param :multipart/temp-file-part)
(dissoc data :visualisation))
如果您控制数据的形状或可以重新排列它,我会考虑像这样更容易规范的东西:
{:visualisation "foo"
:files {:file-1 {,,,}
:file-2 {,,,}}}
我想创建一个 clojure 规范来验证由 reitit.ring.middleware.multipart
中间件创建的 http 请求的 :multipart
参数。
多部分表单数据必须包含特定参数,这些参数可以使用 s/keys
和任意数量的具有任意参数名称的文件进行验证。
要验证的地图如下所示:
{:visualisation "vis"
:file-xy {:filename "foo.png",
:content-type "image/png",
:tempfile "C:\Temp\ring-multipart-123.tmp",
:size 295281}
:file-abc {:filename "bar.png",
:content-type "image/png",
:tempfile "C:\Temp\ring-multipart-456.tmp",
:size 42}}
我可以像这样使用 reitit.ring.middleware.multipart/temp-file-part
规范验证文件:
(s/def :multipart/files (s/map-of :multipart/param multipart/temp-file-part))
综合起来,我想出了一个通过的规范,但它允许所有未知参数是文件或字符串:
(s/def :multipart/param keyword?)
(s/def :multipart/visualisation string?)
(s/def :multipart/items (s/map-of :multipart/param (s/or :file multipart/temp-file-part :visualisation string?)))
(s/def :visualisation/files (s/and (s/keys :req-un [:multipart/visualisation])
:multipart/items))
如何为具有特定键的映射定义规范,并为其他键定义值验证器?
您可以添加谓词函数以确保只有一个映射值是字符串:
(s/def :visualisation/files
(s/and (s/keys :req-un [:multipart/visualisation])
#(= 1 (count (filter string? (vals %))))
:multipart/items))
(s/conform :visualisation/files
{:visualisation "vis"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
(s/conform :visualisation/files
{:visualisation "vis"
:file-abc "not valid"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
但是如果您使用 conform
的输出,包罗万象的 s/or
规范将产生冗余标签。
另一种选择是使用两个规范检查:
(def data
{:visualisation "vis"
:file-xy {:filename "" :content-type "" :tempfile "" :size 0}})
(s/conform (s/keys :req-un [:multipart/visualisation])
data)
(s/conform (s/map-of :multipart/param :multipart/temp-file-part)
(dissoc data :visualisation))
如果您控制数据的形状或可以重新排列它,我会考虑像这样更容易规范的东西:
{:visualisation "foo"
:files {:file-1 {,,,}
:file-2 {,,,}}}