validate schema with key and value using plumatic schema

630 views Asked by At

I'm trying to do a validation for key value in a vector using plumatic-schema but the error message is not clear for me, here's what I'm trying to do:

;validating array with maps, it works
(s/validate [{}] [{} {}])
=> [{} {}]

;validating array with key and map (any lenght), not work
(s/validate [s/Int {}] [0 {} 1 {}])
[Int {}] is not a valid sequence schema; 
a valid sequence schema consists of zero or more `one` elements, followed by zero or more
`optional` elements, followed by an optional schema that will match the remaining elements.

My question is, do you know what am I doing wrong? And the real meaning of this error?

The goal actually is to use this validation for a function call,

eg:

  (s/defn example [items :- [(s/one s/Int "i") (s/one {} "v")]] ...)
  
  ;the call should be valid for cases like this 
  (example [0 {} 1 {} 2 {} 3 {}])
  (example [0 {}])
1

There are 1 answers

0
Alan Thompson On

See these docs:

Here is code showing how it works:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [schema.core :as s]))

(dotest
  (is= [{} {}]
       (spyx (s/validate
               [{}]
               [{} {}])))

  (is= [0 {}]
       (s/validate
         [(s/one s/Int "int-1")
          (s/one {} "map-2")]
         [0 {}]))

  (is= [0 {} 1 {}]
       (s/validate
         [(s/one s/Int "int-1")
          (s/one {} "map-2")
          (s/one s/Int "int-3")
          (s/one {} "map-4")]
         [0 {} 1 {}]))  )

If you want to validate arbitrary lengths of alternating int & map, you may have to do a little prep work:

(defn validate-alternate-int-and-map
      [some-seq]
      (let [pairs   (partition 2 some-seq)
            all-int (mapv first pairs)
            all-map (mapv second pairs)]
        (assert (= (count all-map)
                   (count all-int)))
        (s/validate [s/Int] all-int)
        (s/validate [{}] all-map)
        some-seq))

(dotest
  (is= [0 {}]            (validate-alternate-int-and-map [0 {}]))
  (is= [0 {} 1 {}]       (validate-alternate-int-and-map [0 {} 1 {}]))
  (is= [0 {} 1 {} 2 {}]  (validate-alternate-int-and-map [0 {} 1 {} 2 {}]))
  )

P.S.

I also have some pre-defined schemas (e.g. KeyMap, Pair, etc) that I find very handy in the tupelo.schema namespace.