metosin / metosin/compojure-api
Pure map schemas are broken
Nessuno ha ancora preso questa issue.
- Lingua principale
- Clojure
- Stelle
- 1.1k
- Fork
- 146
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
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
...
}
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con compojure.api.coercion.core/named-coercion e compojure.api.coercion.schema/json-coercion-matcher, quindi segui la configurazione del decoder JSON di Muuntaja mostrata nella issue. Riproduci una richiesta usando lo schema di map puro {s/Str s/Str}; il lavoro è completato quando le chiavi stringa rimangono stringhe durante la deserializzazione e la coercizione, senza compromettere le map con chiavi di schema.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- clojure, openapi
- Ambito
- api, backend
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 28/100