compojure-api spec coercion on response body
我试图弄清楚如何使用compojure-api和spec做自定义强制。 通过阅读文档和代码,我可以对输入(正文)进行强制转换,但是无法对响应正文进行强制转换。
具体来说,我有一个自定义类型,一个时间戳,在我的应用中表示为long类型,但是对于Web API,我想使用并返回ISO时间戳(不,我不想在内部使用Joda)。
以下是我可用于输入强制的内容,但无法正确强制响应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | (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)) |
问题在于规格符合是单向转换管道:
为了支持双向转换,您需要将最终结果定义为以下两种可能的格式之一:将您的谓词更改为类似
或者,您可以有两个不同的规格记录,一个用于输入(带
如果有额外的
通常,返回转换由格式编码器完成,但它们通常在值类型上分派。例如,柴郡(Cheshire)看到一个Long,却不知道应将其写为日期字符串。
也许#clojure-spec懈怠的人可能会有所帮助。还想知道如何使用规范构建这种双向转换。