@ikitommi some sort of (st/add-custom-coersion [:body :formats "application/json" :timestamp] json-timestamp->long)
would be a nice function to have.
for some permutation of [:body :formats "application/json" :timestamp]
What if we turn this around and add the coercers directly to Spec (Records)?
Yeah!
(st/spec
{:pred (partial DateTime)
:coercion {:string str->date-time}
:json-schema/examples "..."})
(st/spec {:coercer json-timestamp->long :type :timestamp})
👍
🙂
yeah, you need the map there right?
So the keys in the coercion-map would be #{:string :json :edn}
?
and how would you then control which part of the lifecycle you’d want coercion in (request/response)?
There are three scopes for coercion (`:request`, :response
and :string
), but only two modes (`:json` and :string
).
I guess if you need finegrained control, you do as you did in your gist.
make the simple case simple, and the hard case possible 🙂
As a newcomer to this project, I guess the fact that :string is present both in scope and mode kind of confuses me. But that might just be me.
That is confusing.
the Spec Records should not know anything about the request/response, but they should know what kind of coercion should occur. Schema had string
and json
.
spec-tools has those too
And don’t get me wrong. I’m super happy for this work and your help.
Any criticism here is just so we can make this better.
thanks, want to make things easy too. There was an idea with schemas, how to bundle ceorcion + encoding + decoding into a one concept: adding a type could be done in one place. I think we could do that now, for both Schemas & Specs. Idea is described here: https://github.com/metosin/web-schemas
As jsonista supports explicit mappings (opposed to Cheshire having global extensions), we can do this now.
e.g. introduce MyNewType
, one can describe all the things (encode, decode (multiple formats: json, edn, transit), coercion in different types, docs) in single definition. With syntax validation. Muuntaja, Jsonista and Schema/Spec-tools would take parts of those and together they would just work. And there would be a test-suite: “which types can I pass in which contexts?”
Currently, if a EDN-writer is missing for a custom type, it can fail at runtime when first time tried to pass over the wire. Temporal runtime coupling. Which is BAD.
Spec Record could be the host for all the info, just need to figure out the format in which. Ideas welcome.
And this should be a small micro-library, might be good for other web libs too.
can’t remember how this is/was solved in the java/scala-land.
It’s a bit much for me to wrap my head around right now 🙂
me too, off to lunch 😉
Ok 😉
It could be cool if the coercer was a multi-method though?
(defmethod coerce [:time-tamp :json :request] [{:keys [value]] ...)
(defmulti coerce type-mode-scope)
(defn type-mode-scope [{:keys [type mode scope]}] [type mode scope])
Or something along these lines.
Problem with this is that you get the temporal coupling. If I don’t implement the multi-method for a given type/mode/scope combination, it might blow up in production.