You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clojure Spec验证失败:JSON解析数据不符合规格定义

解决Clojure Spec验证JSON数据失败的两个问题

针对你遇到的两个验证失败问题,直接给你可行的解决办法:

问题1:解析后的数据外层带:invoice键,与Spec期望的内部结构不匹配

你有两种选择来修复:

选项1:调整Spec结构,适配外层的:invoice键

新增一个顶层Spec来匹配整个JSON的外层结构,内部复用你已定义的::invoice/invoice:

(require '[clojure.spec.alpha :as s])

;; 新增顶层wrapper Spec
(s/def ::invoice-wrapper (s/keys :req-un [::invoice/invoice]))

;; 验证时使用这个新Spec
(s/valid? ::invoice-wrapper (invoice "invoice.json"))

选项2:验证前提取:invoice对应的内部数据

直接从解析后的map中取出:invoice的值再验证,不用改原Spec:

(s/valid? ::invoice/invoice (:invoice (invoice "invoice.json")))

问题2:JSON中retentions的tax_rate是double类型,与Spec的int?定义不匹配

根据业务需求选下面的方案:

方案1:放宽Spec的类型限制(允许整数和浮点数)

如果业务上tax_rate可以是数字类型(不管整数还是小数),把Spec里的int?改成number?:

(s/def ::tax_rate number?)

方案2:解析JSON时将double转成整数(如果业务要求必须是整数)

如果tax_rate必须是整数,在解析JSON时把符合整数条件的double转成int。假设你用cheshire解析JSON,可以加自定义解码逻辑:

(require '[cheshire.core :as json])

(defn parse-invoice [path]
  (json/parse-string (slurp path) true
    {:key-fn keyword
     ;; 把整数型的double转成int,非整数的保持原样(可选调整)
     :decode-double (fn [d] (if (zero? (rem d 1)) (int d) d))}))

;; 验证时用解析后的结果
(s/valid? ::invoice/invoice (:invoice (parse-invoice "invoice.json")))

如果已经有解析函数,也可以手动遍历数据转换tax_rate:

(defn fix-tax-rates [invoice-data]
  (update invoice-data :retentions
    (fn [retentions]
      (mapv #(update % :tax_rate int) retentions))))

;; 先提取内部数据,再修复类型,最后验证
(s/valid? ::invoice/invoice (-> (invoice "invoice.json") :invoice fix-tax-rates))

内容的提问来源于stack exchange,提问作者vcFull

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:01:03