【问题标题】:compojure-api spec coercion on response body响应主体上的 compojure-api 规范强制
【发布时间】:2018-03-23 22:59:40
【问题描述】:

我试图弄清楚如何使用 compojure-api 和规范进行自定义强制。通过阅读文档和代码,我能够对输入(正文)进行强制转换,但无法对响应正文进行强制转换。

具体来说,我有一个自定义类型,一个时间戳,它在我的应用程序中表示为 long,但对于 Web API,我想使用并返回 ISO 时间戳(不,我不想在内部使用 Joda)。

以下是我拥有的可用于输入强制的内容,但我无法正确强制响应。

(ns foo
  (:require [clj-time.core :as t]
            [clj-time.coerce :as t.c]
            [spec-tools.conform :as conform]
            [spec-tools.core :as st]))


(def timestamp (st/create-spec
            {:spec pos-int?
             :form `pos-int?
             :json-schema/default "2017-10-12T05:04:57.585Z"
             :type :timestamp}))

(defn json-timestamp->long [_ val]
  (t.c/to-long val))

(def custom-json-conforming
  (st/type-conforming
   (merge
    conform/json-type-conforming
    {:timestamp json-timestamp->long}
    conform/strip-extra-keys-type-conforming)))

(def custom-coercion
  (->  compojure.api.coercion.spec/default-options
       (assoc-in [:body :formats "application/json"] custom-json-
conforming)
       compojure.api.coercion.spec/create-coercion))

;; how do I use this for the response coercion?
(defn timestamp->json-string [_ val]
  (t.c/to-string val))
;; I've tried the following but it doesn't work:
#_(def custom-coercion
  (->  compojure.api.coercion.spec/default-options
       (assoc-in [:body :formats "application/json"] custom-json-
conforming)
       (assoc-in [:response :formats "application/json"]
                 (st/type-conforming
                  {:timestamp timestamp->json-string}))
       compojure.api.coercion.spec/create-coercion))

【问题讨论】:

    标签: clojure compojure-api


    【解决方案1】:

    问题在于 Spec Conforming 是一种单向转换管道:

    s/conform(正因为如此st/conform)对结果进行转换和验证。您的响应强制首先将整数转换为日期字符串,然后根据原始规范谓词(pos-int?)对其进行验证,但它失败了。

    要支持双向转换,您需要将最终结果定义为任何一种可能的格式:例如将您的谓词更改为#(or (pos-int? %) (string? %)) 之类的东西,它应该可以工作。

    或者您可以有两个不同的规范记录,一个用于输入(timestamp-longpos-int? 谓词),另一个用于输出(timestamp-stringstring? 谓词)。但是需要记住使用正确的请求和响应。

    CLJ-2251 如果有额外的:transform 模式(还没有写在问题中)可能会有所帮助,这将在不验证最终结果的情况下进行符合。

    通常,返回转换由格式编码器完成,但它们通常在值类型上分派。例如 Cheshire 只看到一个 Long 并且不知道它应该写为日期字符串。

    也许#clojure-spec slack 上的人可以提供帮助。也想知道如何使用规范构建这种双向转换。

    【讨论】:

    • 拥有#(or (pos-int? %) (string? %)) 将允许字符串通过规范,但如何调用t.c/to-string 函数?意思是,我如何将timestamp->json-string 与胁迫者挂钩?
    猜你喜欢
    • 2022-01-19
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 2022-07-18
    • 2018-09-15
    • 2018-12-22
    • 2018-02-28
    相关资源
    最近更新 更多