plumatic / schema

Clojure(Script) library for declarative data description and validation
Other
2.4k stars 256 forks source link

Support for nested abstract map schemas #363

Open patapizza opened 8 years ago

patapizza commented 8 years ago

It seems like I can't nest abstract map schemas.

Eval'ing

(s/defschema A
  (sam/abstract-map-schema :type {}))
(sam/extend-schema AA A ["type"] {})

(s/defschema B
  (sam/abstract-map-schema :bar {}))
(sam/extend-schema BB B ["bar"] A)

(s/checker {:x B})

yields

Unhandled clojure.lang.Compiler$CompilerException
Caused by java.lang.IllegalArgumentException
No implementation of method: :spec of protocol:
#'schema.core/Schema found for class: clojure.lang.Boolean

Replacing A by AA in the BB extension yields a similar exception, this time with clojure.lang.Symbol.

w01fe commented 8 years ago

I'm not sure exactly what you're trying to do, but the last argument of extend-schema should be a map from key to value, and A isn't that.

(sam/extend-schema BB B ["bar"] {:a A})

or similar should work, I think -- is that what you're looking for?

patapizza commented 8 years ago

Thanks for your response.

I would like to reuse an abstract map schema as extension of another abstract map schema. Consider the use case where I categorize animals by name (cat), and cat features by color (black, white).

(s/defschema CatFeatures
  (sam/abstract-map-schema :color {}))
(sam/extend-schema BlackCatFeatures CatFeatures ["black"] {})
(sam/extend-schema WhiteCatFeatures CatFeatures ["white"] {})

(s/defschema Animal
  (sam/abstract-map-schema :name {}))
(sam/extend-schema Cat Animal ["cat"] CatFeatures)

(s/checker {:x Animal})

Is there a way to achieve this, without duplicating schemas?

w01fe commented 8 years ago

Thanks for the explanation. That's unfortunately not possible currently -- the last argument to extend-schema has to be an ordinary map schema. I think it should be straightforward to build a variant of abstract-map-schema that does what you want, however.