序列中的可选元素
Optional element in sequence
我正在尝试使用 Prismatic/Schema 匹配以下序列:
[{:n "some text"}] ; => valid
和
[{:k "some text"} {:n "some text"}] ; => valid
我尝试过的:
(s/def Elem3
{:k s/Str})
(s/def Elem2
{:n s/Str})
(s/def Elem
[(s/optional Elem2 "elem2") Elem3])
(s/validate Elem [{:k "huji"}])
;; =>
;; Value does not match schema: [(named {:n missing-required-key, :k
;; disallowed-key} "elem2")]
(s/def Elem
[(s/maybe Elem2) Elem3])
(s/validate Elem [{:k "huji"}])
;; =>
;; [(maybe {:n Str}) {:k java.lang.String}] is not a valid sequence
;; schema; a valid sequence schema consists of zero or more `one`
;; elements, followed by zero or more `optional` elements, followed by
;; an optional schema that will match the remaining elements.
(s/defrecord ElemOption1
[elem3 :- Elem3])
(s/defrecord ElemOption2
[elem2 :- Elem2
elem3 :- Elem3])
(s/def Elem
(s/conditional
#(= 2 (count %)) ElemOption2
:else ElemOption1))
(s/validate Elem [{:k "huji"}])
;; =>
;; Value does not match schema: (not (instance?
;; peg_dsl.standard_app.ElemOption1 [{:k "huji"}]))
主要问题是没看懂怎么写
允许省略指定向量的第一个元素的模式。
匹配上面两个向量的正确方法是什么?
您第一次尝试的问题是从
optional 意味着它期望 {:k s/Str} 或什么都没有,它正在看到
{:n s/Str}
,显然不对。
你的第二次尝试有两个问题。 Maybe
可以是值
或 nil
,但它必须存在。你也没有写
正确排序架构。但是序列模式的问题
是元素需要按 s/one* s/optional*
的顺序排列,而你
想要 s/optional s/one
.
你的第三次尝试更接近,使用条件,但你
无法匹配,因为您没有验证
记录,您正在验证地图。
解决方案如下所示:
(def ElemKNList [(s/one {:k s/Str} "k") (s/one {:n s/Str} "n")])
(def ElemNList [(s/one {:n s/Str} "n")])
(def Elem (s/conditional #(= 2 (count %)) ElemKNList
:else ElemNList))
(s/validate Elem [{:k "huji"} {:n "huji"}])
=> [{:k "huji"} {:n "huji"}]
(s/validate Elem [{:n "huji"}])
=> [{:n "huji"}]
(s/validate Elem [{:k "huji"}])
=> ExceptionInfo Value does not match schema: [(named {:n missing-required-key, :k disallowed-key} "n")] schema.core/validator/fn--18435 (core.clj:151)
我正在尝试使用 Prismatic/Schema 匹配以下序列:
[{:n "some text"}] ; => valid
和
[{:k "some text"} {:n "some text"}] ; => valid
我尝试过的:
(s/def Elem3
{:k s/Str})
(s/def Elem2
{:n s/Str})
(s/def Elem
[(s/optional Elem2 "elem2") Elem3])
(s/validate Elem [{:k "huji"}])
;; =>
;; Value does not match schema: [(named {:n missing-required-key, :k
;; disallowed-key} "elem2")]
(s/def Elem
[(s/maybe Elem2) Elem3])
(s/validate Elem [{:k "huji"}])
;; =>
;; [(maybe {:n Str}) {:k java.lang.String}] is not a valid sequence
;; schema; a valid sequence schema consists of zero or more `one`
;; elements, followed by zero or more `optional` elements, followed by
;; an optional schema that will match the remaining elements.
(s/defrecord ElemOption1
[elem3 :- Elem3])
(s/defrecord ElemOption2
[elem2 :- Elem2
elem3 :- Elem3])
(s/def Elem
(s/conditional
#(= 2 (count %)) ElemOption2
:else ElemOption1))
(s/validate Elem [{:k "huji"}])
;; =>
;; Value does not match schema: (not (instance?
;; peg_dsl.standard_app.ElemOption1 [{:k "huji"}]))
主要问题是没看懂怎么写 允许省略指定向量的第一个元素的模式。 匹配上面两个向量的正确方法是什么?
您第一次尝试的问题是从
optional 意味着它期望 {:k s/Str} 或什么都没有,它正在看到
{:n s/Str}
,显然不对。
你的第二次尝试有两个问题。 Maybe
可以是值
或 nil
,但它必须存在。你也没有写
正确排序架构。但是序列模式的问题
是元素需要按 s/one* s/optional*
的顺序排列,而你
想要 s/optional s/one
.
你的第三次尝试更接近,使用条件,但你 无法匹配,因为您没有验证 记录,您正在验证地图。
解决方案如下所示:
(def ElemKNList [(s/one {:k s/Str} "k") (s/one {:n s/Str} "n")])
(def ElemNList [(s/one {:n s/Str} "n")])
(def Elem (s/conditional #(= 2 (count %)) ElemKNList
:else ElemNList))
(s/validate Elem [{:k "huji"} {:n "huji"}])
=> [{:k "huji"} {:n "huji"}]
(s/validate Elem [{:n "huji"}])
=> [{:n "huji"}]
(s/validate Elem [{:k "huji"}])
=> ExceptionInfo Value does not match schema: [(named {:n missing-required-key, :k disallowed-key} "n")] schema.core/validator/fn--18435 (core.clj:151)