spec-tools
spec-tools copied to clipboard
Support for s/cat and regex ops (s/*, s/?, s/+) in data specs, with decoding
Hi there,
I am seeing some interesting results when I try and perform decoding on data specs with s/cat and regex ops.
For example, given the following example data specs:
(def sub-widget-a-spec
(std/spec
{:name ::sub-widget-a
:spec {:a-prop pos-int?}}))
(def sub-widget-b-spec
(std/spec
{:name ::sub-widget-b
:spec {:b-prop pos-int?}}))
(def sub-widget-c-spec
(std/spec
{:name ::sub-widget-c
:spec {:c-prop pos-int?}}))
(def widget-spec
(std/spec
{:name ::widget-spec
:spec {:the-sub-widget (s/cat
:sub-widget-a (std/spec {:name ::sub-widget-a
:spec sub-widget-a-spec})
:sub-widget-b (s/? (std/spec {:name ::sub-widget-b
:spec sub-widget-b-spec}))
:sub-widget-c (s/* (std/spec {:name ::sub-widget-c
:spec sub-widget-c-spec})))}}))
If I try and generate some sample data using the data spec, all is good and I see the regex op rules and ordering being adhered to for the sequence:
(gen/generate (s/gen widget-spec))
{:the-sub-widget ({:a-prop 22} {:c-prop 19} {:c-prop 1} {:c-prop 7436}
However, if I then try to perform decoding either with st/coerce
or st/decode
, for example decoding on already-encoded data, the data is left as-is (as in, it remains string encoded):
(def widget-encoded (st/encode widget-spec (gen/generate (s/gen widget-spec)) st/string-transformer))
widget-encoded
{:the-sub-widget ({:a-prop "285981"} {:b-prop "24438"} {:c-prop "844"} {:c-prop "102400766"} {:c-prop "1395"})}
With st/coerce
:
(st/coerce widget-spec widget-encoded st/string-transformer)
{:the-sub-widget ({:a-prop "285981"} {:b-prop "24438"} {:c-prop "844"} {:c-prop "102400766"} {:c-prop "1395"})}
With st/decode
:
(st/decode widget-spec widget-encoded st/string-transformer)
{:the-sub-widget ({:a-prop "285981"} {:b-prop "24438"} {:c-prop "844"} {:c-prop "102400766"} {:c-prop "1395"})}
Since st/decode
uses st/coerce
, it seems reasonable to assume that the issue lies inside the latter.
It's worth noting that st/conform
followed by s/unform
, instead of st/decode
or st/coerce
seems to work as expected:
(s/unform widget-spec (st/conform widget-spec widget-encoded st/string-transformer))
{:the-sub-widget ({:a-prop 285981} {:b-prop 24438} {:c-prop 844} {:c-prop 102400766} {:c-prop 1395})}