spec-tools icon indicating copy to clipboard operation
spec-tools copied to clipboard

Support for regex ops (s/*, s/?, s/+) and optional keys in data specs, with encoding and decoding

Open alza-bitz opened this issue 5 years ago • 1 comments

With the fix for #146 in PR #148, the following now encodes and decodes successfully:

(def cat-spec
  (std/spec {:name ::int-or-double-or-both :spec (s/cat :a (s/? (std/spec {:name ::a-spec
                                                                           :spec {:an-int int?}}))
                                                        :b (s/? (std/spec {:name ::b-spec
                                                                           :spec {:a-double double?}})))}))

Encoding...

(st/encode cat-spec (gen/generate (s/gen cat-spec)) st/string-transformer)
; ({:an-int "-6130"})
(st/encode cat-spec (gen/generate (s/gen cat-spec)) st/string-transformer)
; ({:an-int "-36964"} {:a-double "-0.1527557373046875"})
(st/encode cat-spec (gen/generate (s/gen cat-spec)) st/string-transformer)
; ()
(st/encode cat-spec (gen/generate (s/gen cat-spec)) st/string-transformer)
; ({:a-double "-0.056640625"})

Decoding... (using st/conform)

(st/conform cat-spec '({:an-int "1"}) st/string-transformer)
; {:a {:an-int 1}}
(st/conform cat-spec '({:a-double "0.060546875"}) st/string-transformer)
; {:b {:a-double 0.060546875}}

However, if a key is made optional, the encoding fails:

(def cat-with-opt-key-spec
  (std/spec {:name ::int-or-double-or-both :spec (s/cat :a (s/? (std/spec {:name ::a-spec
                                                                           :spec {(std/opt :an-int) int?}}))
                                                        :b (s/? (std/spec {:name ::b-spec
                                                                           :spec {:a-double double?}})))}))
(st/encode cat-with-opt-key-spec (gen/generate (s/gen cat-with-opt-key-spec)) st/string-transformer)
; ({:a-double -7.5938720703125}) FAIL

Similarly, when using st/conform, decoding also fails:

(st/conform cat-with-opt-key-spec '({:an-int "1"}) st/string-transformer)
; {:a {:an-int 1}}
(st/conform cat-with-opt-key-spec '({:a-double "0.060546875"}) st/string-transformer)
; {:a {:a-double "0.060546875"}} FAIL

alza-bitz avatar May 02 '19 01:05 alza-bitz

Hi @ikitommi,

I was just wondering if there's any chance this could be looked into? I reported it but didn't investigate any further at the time, because I mistakenly believed I wasn't affected by it.

It turns out I was incorrect, and optional numeric values in my data specs weren't being encoded to string due to this issue; I didn't see it because I'm using data.xml on the output from st/encode, and this was converting numeric values to string for me, without me realising.

I recently discovered this when I wanted to change the data specs in my project to use other, custom types (which need to be optional), and then I hit this issue more visibly - I got an error from data.xml about my custom type not being supported.

I'm not sure if I'd have much time to help in this instance, although I previously contributed a fix for some possibly-related issues, #146 and #147.

Thanks!

Alex.

alza-bitz avatar Oct 15 '19 22:10 alza-bitz