使用 Plumatic Sc​​hema 强制转换为 bigdec

Posted

技术标签:

【中文标题】使用 Plumatic Sc​​hema 强制转换为 bigdec【英文标题】:Using Plumatic Schema to coerce to bigdec 【发布时间】:2016-09-28 13:35:59 【问题描述】:

我有 :loan/amount 1200 类型的传入数据。

是否可以使用 plumatic Schema 将其强制转换为 :loan/amount 1200M,即将数字(甚至数字字符串)强制转换为大小数?

我不知道如何定义一个新的数据类型(如s/Bigdec),然后确保它使用clojure.core/bigdec 将某个值强制转换为java.math.BigDecimal

【问题讨论】:

【参考方案1】:

Schema 中有两个独立的概念:验证和强制。

对于第一个,您需要定义您的架构。类被视为模式,因此您无需为java.math.BigDecimal 创建自定义模式。您的架构可能如下所示:

(require '[schema.core :as s])
(require '[schema.coerce :as c])

(s/defschema Loan :loan/amount java.math.BigDecimal)

现在您可以根据架构验证您的数据:

(s/validate Loan :loan/amount 10M)
;; => :loan/amount 10M

现在,如果您有一些想要强制的数据,则需要定义一个强制函数,该函数是从所需目标模式(在您的情况下为 java.math.BigDecimal)到将实际值转换为所需的bigdec 值。

(def safe-bigdec (c/safe bigdec)

schema.coerce/safe 是一个实用函数,它包装了原始函数,如果原始函数在调用时抛出异常,safe 将返回原始输入值而不是抛出异常。

我们的 matcher 函数将检查当前 schema 元素是否为 BigDecimal 并返回转换函数或 nil 否则(意味着对其他类型没有强制):

(defn big-decimal-matcher [schema]
  (when (= java.math.BigDecimal schema)
    safe-bigdec))

最后我们需要一个强制器来执行实际的强制:

(def loan-coercer (c/coercer Loan big-decimal-matcher))

完成所有设置后,我们现在可以使用我们的强制器了:

(loan-coercer :loan/amount "12.34")
;; => :loan/amount 12.34M

(loan-coercer :loan/amount 1234)
;; => :loan/amount 1234M

(loan-coercer :loan/amount "abc")
;; => #schema.utils.ErrorContainer:error :loan/amount (not (instance? java.math.BigDecimal "abc"))

【讨论】:

哇,非常感谢@piotrek-bzdyl!这正是我所需要的(我希望其他人也需要)。

以上是关于使用 Plumatic Sc​​hema 强制转换为 bigdec的主要内容,如果未能解决你的问题,请参考以下文章

使用 Prismatic Sc​​hema 验证多个多态值

使用 toPandas 时强制将 null 一致转换为 nan

SQL数据库查看所有外键

如何强制 ADO.Net 在阅读器 TableSchema 中仅使用 System.String DataType

mysql命令总结

表值函数返回类型