malli

Chris Chen 2025-12-06T11:28:10.831889Z

I can't tell if this is a "me" problem or a library problem - but I have a situation where I'm maintaining several parallel type registries (for a progressive typing system involving structured data extraction). The "loose" types go to an LLM to be used with the structured outputs, and they're generally relaxed from the defined "strict" types (e.g. a temporal type might be a simple string in extraction but a full discriminated union after extraction). The problem I'm having is that by default json-schema/transform deref's with respect to the global default registry - is there a way to make it deref wrt the :registry option in the argument?

opqdonut 2025-12-08T08:10:31.726629Z

No, I botched the test case, it does seem to work.

opqdonut 2025-12-08T08:14:45.025219Z

See my PR, these all seem to work:

(json-schema/transform [:map {:registry {::foo :string}} [:s ::foo]])

(json-schema/transform [:map [:s ::foo]] {:registry (merge (m/default-schemas) {::foo :string})})

(json-schema/transform [:map [:s [:schema ::foo]]] {:registry (merge (m/default-schemas) {::foo :string})})

(json-schema/transform [:map [:s [:ref ::foo]]] {:registry (merge (m/default-schemas) {::foo :string})})
Is your case something different?

Chris Chen 2025-12-08T12:38:18.230079Z

No you've covered how I was using it (same structure as the 2nd testcase) and it seems consistent when I test it again. In that case the issue might be to do with the custom behaviour of my loosener - I realise it might just be happening for custom replacement types that override the typical behaviour. Thx for checking.

👍 1
Chris Chen 2025-12-08T12:49:38.184029Z

Actually the issue seems to persist when loaded into another codebase as a library (but interestingly not when kept within the same codebase)

Chris Chen 2025-12-07T23:21:42.010469Z

I realised why this was happening - not sure if this constitutes an issue or this is intended behaviour. The docs section on cache behaviour make it seem like it might be intentional. By default json-schema/transform doesn't seem to pass registry options to deref - but also the cache behaviour makes it so that keyword names for types are bound to the first instance of assignment (so if I build a "strict type system" and then "loosen" it while preserving keyword references to complex types, the keywords are going to refer to the "strict" variants)

opqdonut 2025-12-08T06:52:10.122999Z

Interesting, there might definitely be bugs in the registry part of the code.

opqdonut 2025-12-08T07:55:30.422309Z

Clear bug: https://github.com/metosin/malli/pull/1248

Chris Chen 2025-12-06T11:34:30.256979Z

On this topic - is there a way to pass an argument to m/deref-recursive so that it ignores certain keywords/custom types