NorfairKing / autodocodec

self(auto)- documenting encoders and decoders
MIT License
121 stars 20 forks source link

Need help with conditional fields #35

Closed m1-s closed 1 year ago

m1-s commented 1 year ago

I have a yaml where one fields dictates which other fields need to be present:

type: type1
field1_of_type1: foo
field2_of_type1: bar

If type has a different value, other fields need to be present:

type: type2
field1_of_type2: baz

In Haskell the data structure look like this:

data MyType where
     MyType :: (MyTypeClass a) => a -> MyType

-- I managed to write a FromJSON instance
instance FromJSON MyType where
    parseJSON = withObject "MyType" $ \o -> case H.lookup "type" o of
        Just (String "type1") -> MyType <$> type1Parser o
        Just (String "type2") -> MyType <$> type2Parser o

How would I translate this to autodocodec? I tried to use matchChoicesCodec, literalTextCodec or parseAlternatives but somehow got none of those to work.

Currently I have the following which does not compile:

type1Codec :: JSONObjectCodec Type1
type1Codec =
    Type1 <$> requiredField' "field1_of_type1"
        A..= field1
        <$> requiredField' "field2_of_type1"
        A..= field2

instance HasCodec MyType where
    codec =
        matchChoicesCodec
            [ (\o -> if lookup "type" o == Just (String "type1") then Just o else Nothing, type1Codec)
            ]
            (someFallBackCodec)
NorfairKing commented 1 year ago

Have a look here: https://github.com/NorfairKing/autodocodec/issues/9

Long-story short: it's not possible in general but it may be possible in specific cases.