malli

opqdonut 2025-05-12T11:03:45.853629Z

https://clojurians.slack.com/archives/C06MAR553/p1747047810978109

šŸ‘ 2
šŸ˜ž 1
🦸 1
šŸŽ‰ 8
cch1 2025-05-12T22:35:00.894949Z

It's ironic that https://potetm.com/devtalk/stability-by-design.html came out today. I'm sure there are good reasons for changing the signatures of parse and unparse, but for us it felt like "throwing wine glasses on the floor."

opqdonut 2025-05-13T04:56:26.109099Z

I feel you. The change was necessary to make unparse more usable, and to make parse return useful output even in weird situations. Some background in the tickets linked to the backlog.

šŸ‘ 1
mafcocinco 2025-05-12T17:50:45.550899Z

I’m new to using malli for OpenAPI/Swagger documentation generation. I asked ChatGPT if malli supports correct output of OpenAPI documents (re: using oneOf or discriminated unions) when a schema contains the multi key. It said that malli did not support this feature but I wanted to verify first. I could not find any mention of this one way or the other on the documentation page, though I certainly could have missed it. Thanks.

Samuel Ludwig 2025-05-12T17:59:07.346459Z

i would trust the docs more than your LLM of choice, #reitit may be more interesting to you if you're looking at OpenAPI and associated architecture, and is also built to work well with malli

mafcocinco 2025-05-12T18:06:07.911199Z

Thanks.

mafcocinco 2025-05-12T19:19:35.050009Z

Did a little experiment with the ring-malli-swagger example in reitit and the answer was pretty clear:

WARNING: Unsupported schema for OpenAPI (expected :map schema) {:in :query} [:multi {:dispatch :type} [:sized [:map {:closed true} [:type :keyword] [:size [:int {:min 0}]]]] [:human [:map {:closed true} [:type :keyword] [:name [:string {:min 1}]]]]]

mafcocinco 2025-05-12T19:19:56.503229Z

This was the route

["/multi"
        {:get {:summary "test multi schema"
               :parameters {:query [:multi {:dispatch :type}
                                    [:sized [:map [:type :keyword] [:size [:int {:min 0}]]]]
                                    [:human [:map [:type :keyword] [:name [:string {:min 1}]]]]]}
               :responses {200 {:body [:map [:message [:string {:min 1}]]]}}
               :handler (fn [_] {:status 200 :body {:message "OK"}})}}]

opqdonut 2025-05-13T05:00:46.136149Z

:multi gets converted to oneOf but you can't have a :multi for the :query parameters. Even OpenAPI can't express that: each query parameter is listed separately. The query parameters are wrapped into a malli :map just for convenience, it's not an actual map. Does that make sense?

opqdonut 2025-05-13T05:01:27.027269Z

here's the code: https://github.com/metosin/malli/blob/master/src/malli/json_schema.cljc#L125

opqdonut 2025-05-13T05:02:39.175829Z

we could probably have an example with a :multi ... I'll add one

opqdonut 2025-05-13T05:23:53.870809Z

https://github.com/metosin/reitit/pull/740

opqdonut 2025-05-13T05:26:31.008339Z

[:multi {:dispatch :type}
 [:literal [:map
            [:type [:= :literal]]
            [:value [:or :int :string]]]]
 [:reference [:map
              [:type [:= :reference]]
              [:description :string]
              [:ref :uuid]]]]
gets converted to
{"oneOf":[{"type":"object",
           "properties":{"type":{"const":"literal"},
                         "value":{"anyOf":[{"type":"integer"},{"type":"string"}]}},
           "required":["type","value"],
           "additionalProperties":false},       
          {"type":"object",
           "properties":{"type":{"const":"reference"},
                         "description":{"type":"string"},
                         "ref":{"type":"string","format":"uuid"}},
           "required":["type","description","ref"],
           "additionalProperties":false}]}}

šŸ‘ 1