metosin / malli

High-performance data-driven data specification library for Clojure/Script.
Eclipse Public License 2.0
1.44k stars 204 forks source link

Feature: Using Java classes as schemas #1007

Open NoahTheDuke opened 5 months ago

NoahTheDuke commented 5 months ago

Occasionally, it is necessary to drop down to Java interop. When that happens, I don't want to lose the ease and simplicity of Malli's validation, and I don't want to have to write my own custom :fn schema each time merely to call (instance? SomeClass value).

It would be helpful to have support for recognizing Java classes, effectively wrapping instance? for general use. I looked at the malli.core code and I'm not entirely sure how to accomplish this or I'd offer to do it.

Thanks so much

ikitommi commented 5 months ago

Something like this:

(defn -class-schema [c]
  (m/-simple-schema
   {:type c
    :pred #(instance? c %)
    :type-properties {:error/message (str "not an instance of class " c)}}))

(defn class-registry
  ([] (class-registry nil))
  ([_options]
   (reify
     mr/Registry
     (-schema [_ type] (when (class? type) (-class-schema type)))
     (-schemas [_]))))

(def registry
  (mr/composite-registry
   m/default-registry
   (class-registry)))

(def Schema
  (m/schema
   [:map
    [:str String]
    [:long Long]]
   {:registry registry}))

(-> (m/explain
     Schema
     {:str "kikka"
      :long "123"})
    (me/humanize))
; => {:long ["not an instance of class class java.lang.Long"]}

You can use that if you need this now. Let's add this to malli as optional part, need to define transformers, json-schema mappings etc for them to be complete.

ikitommi commented 5 months ago

original issue #75