如何在Malli Schema中验证日期?遇正则转义及验证失败问题
在Malli中正确验证日期的解决方案
一、使用Malli原生日期类型:local-date
Malli的:local-date类型验证的是**java.time.LocalDate实例**,而非日期字符串。如果你的输入是字符串,需先解析为LocalDate,或自定义验证器直接校验字符串格式:
- 解析字符串为
LocalDate后验证
(require '[malli.core :as m]) (require '[clojure.java-time :as time]) (def schema [:map [:a :int] [:b :local-date]]) ; 将字符串转成LocalDate实例后验证 (m/validate schema {:a 1 :b (time/local-date "2022-07-28")}) ; 返回true
- 自定义字符串日期验证器(兼顾格式与有效性)
正则只能校验格式,无法识别无效日期(如2022-13-01),用:fn结合日期解析更可靠:
(def date-string-schema [:map [:a :int] [:b [:and string? [:fn (fn [s] (try (time/local-date s) true (catch Exception _ false)))]]]]) (m/validate date-string-schema {:a 1 :b "2022-07-28"}) ; 返回true (m/validate date-string-schema {:a 1 :b "2022-13-01"}) ; 返回false(无效日期)
二、解决正则验证的转义与失败问题
你遇到的问题核心是字符串转义错误和Schema键与验证数据不匹配:
1. 正则的正确写法
- 用正则字面量(无需转义):
(def s2 [:map [:orderId string?] [:OrderDate :re #"\d{4}-\d{2}-\d{2}"]])
- 用字符串形式(需双重转义,Clojure字符串中
\是转义字符):
(def s2 [:map [:orderId string?] [:OrderDate :re "\\d{4}-\\d{2}-\\d{2}"]])
2. 验证失败的关键原因
你的Schema定义的键是:orderId和:OrderDate,但验证时传入的是:a和:b,键名完全不匹配,导致验证失败。正确验证代码:
(m/validate s2 {:orderId "123" :OrderDate "2022-07-28"}) ; 返回true
3. JSON Schema转换问题
只要正则写法正确(字面量或转义后的字符串),Malli可正常转换为JSON Schema:
(require '[malli.json-schema :as mjs]) (mjs/transform s2) ; 生成的JSON Schema会包含"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
三、推荐方案
- 若需处理日期逻辑(如计算、比较),优先用
:local-date类型,提前将字符串解析为LocalDate实例。 - 若仅需验证字符串格式,用自定义
:fn验证更可靠(避免正则漏过无效日期)。
内容的提问来源于stack exchange,提问作者MouseNag
相关产品推荐
相关产品推荐

