Pure map schemas are broken
还没有人认领这个 Issue。
评估
调研方向
从 compojure.api.coercion.core/named-coercion 和 compojure.api.coercion.schema/json-coercion-matcher 开始,然后跟踪 issue 中展示的 Muuntaja JSON 解码器配置。使用纯 map schema {s/Str s/Str} 重现一个请求;完成的标准是字符串键在反序列化和 coercion 过程中仍保持为字符串,同时不破坏 schema-keyed map。
由索引模型根据 Issue 内容生成。
描述
Not sure if thats by design, since Swagger doesn't seem to represent well pure maps, i.e. {s/Str s/Str}, but handling of those is broken atm.
What happens is that the default implementation forces Cheshire to keywordize all incoming maps while deserializing, so instead of {s/Str s/Str}, the request winds up as {s/Keyword s/Str} :(
The good (for my use case) news is that since Compojure API is almost infinitely extensible ;) I was able to:
- Override the JSON deserialization
- Plug a custom coercer
Something like this (only the important bits):
(ns blah.core
(:require
;; just to show what cs and cc below resolve to
[compojure.api.coercion.core :as cc]
[compojure.api.coercion.schema :as cs])
;; coercion wiring
(defn keywordize-some
"Keywordizes only the top-level map keys that are in the ks collection"
[ks m]
(reduce (fn [nm k]
(if (keyword? k)
(if-let [existing (get nm k)]
nm
(let [k-str (name k)]
(if-let [ex2 (get nm k-str)]
(-> nm
(assoc k ex2)
(dissoc k-str))
nm)))
nm))
m
ks))
(defn json-coercer [schema x]
"Coerces a map value with a map schema - otherwise falls back to the original coercer"
(if (map? x)
(keywordize-some (keys schema) x)
(if-let [fallback (cs/json-coercion-matcher schema)]
(fallback x)
x)))
(defn jcm [schema]
(if (map? schema)
(partial json-coercer schema)
(cs/json-coercion-matcher schema)))
(defmethod cc/named-coercion :json [_] (cs/create-coercion {:body {:default (constantly nil)
:formats {"application/json" jcm
"application/msgpack" jcm
"application/x-yaml" jcm}}
:string {:default cs/string-coercion-matcher}
:response {:default (constantly nil)}}))
(api
....
;; wire a non-keywordizing JSON deserializer
;; the actual keywordization will be done in a custom coercer
:formats (-> (:formats compojure.api.api/api-defaults)
(assoc-in [:formats muuntaja.format.json/json-type] {:decoder [muuntaja.format.json/make-json-decoder {}]
:encoder [muuntaja.format.json/make-json-encoder]}))
;; our custom coercer registered via defmethod above
:coercion :json
...
}
- 主要语言
- Clojure
- 星标
- 1.1k
- 派生
- 144
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
metosin/compojure-api 的其他 Issue
-
难度 3/5 1-2 天 新手友好度 45/100
metosin/compojure-api#489 ·
-
难度 5/5 一周以上 新手友好度 30/100
metosin/compojure-api#468 ·
-
难度 5/5 一周以上 新手友好度 20/100
metosin/compojure-api#467 ·
-
难度 5/5 一周以上 新手友好度 25/100
metosin/compojure-api#464 ·
-
难度 5/5 一周以上 新手友好度 30/100
metosin/compojure-api#463 · 3 条评论 ·
查看 metosin/compojure-api 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
calcit-lang/calcit#2151 ·
维护者通常 1 天内回复
-
worker/start rejects middleware supplied as a Var可能已有人在做 @rajp152k 于 1 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 75/100
-
Profiler (Remotery) leaks a socket for every connection that fails the WebSocket handshake可能已有人在做 @rthery 于 2 天前认领。 未关闭triage
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
IOP nitrate needs triage
难度 2/5 1-3 小时 新手友好度 66/100
维护者通常 1 天内回复
-
category:tooling
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复