Skip to content

Commit 27dfc4d

Browse files
Merge pull request #15 from LiamGoodacre/feature/config
Add encoding options for which tag & values keys to use
2 parents 10d8ab5 + 9d65c1e commit 27dfc4d

File tree

4 files changed

+76
-21
lines changed

4 files changed

+76
-21
lines changed

src/Data/Argonaut/Decode/Generic/Rep.purs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ module Data.Argonaut.Decode.Generic.Rep (
33
class DecodeRepArgs,
44
class DecodeLiteral,
55
decodeRep,
6+
decodeRepWith,
67
decodeRepArgs,
78
genericDecodeJson,
9+
genericDecodeJsonWith,
810
decodeLiteralSum,
911
decodeLiteralSumWithTransform,
1012
decodeLiteral
1113
) where
1214

1315
import Prelude
16+
import Data.Argonaut.Types.Generic.Rep (Encoding, defaultEncoding)
1417

1518
import Control.Alt ((<|>))
1619
import Data.Argonaut.Core (Json, toArray, toObject, toString)
@@ -26,28 +29,31 @@ import Partial.Unsafe (unsafeCrashWith)
2629
import Prim.TypeError (class Fail, Text)
2730

2831
class DecodeRep r where
29-
decodeRep :: Json -> Either String r
32+
decodeRepWith :: Encoding -> Json -> Either String r
33+
34+
decodeRep :: forall r. DecodeRep r => Json -> Either String r
35+
decodeRep = decodeRepWith defaultEncoding
3036

3137
instance decodeRepNoConstructors :: DecodeRep Rep.NoConstructors where
32-
decodeRep _ = Left "Cannot decode empty data type"
38+
decodeRepWith e _ = Left "Cannot decode empty data type"
3339

3440
instance decodeRepSum :: (DecodeRep a, DecodeRep b) => DecodeRep (Rep.Sum a b) where
35-
decodeRep j = Rep.Inl <$> decodeRep j <|> Rep.Inr <$> decodeRep j
41+
decodeRepWith e j = Rep.Inl <$> decodeRepWith e j <|> Rep.Inr <$> decodeRepWith e j
3642

3743
instance decodeRepConstructor :: (IsSymbol name, DecodeRepArgs a) => DecodeRep (Rep.Constructor name a) where
38-
decodeRep j = do
44+
decodeRepWith e j = do
3945
let name = reflectSymbol (SProxy :: SProxy name)
4046
let decodingErr msg = "When decoding a " <> name <> ": " <> msg
4147
jObj <- mFail (decodingErr "expected an object") (toObject j)
42-
jTag <- mFail (decodingErr "'tag' property is missing") (FO.lookup "tag" jObj)
43-
tag <- mFail (decodingErr "'tag' property is not a string") (toString jTag)
48+
jTag <- mFail (decodingErr $ "'" <> e.tagKey <> "' property is missing") (FO.lookup e.tagKey jObj)
49+
tag <- mFail (decodingErr $ "'" <> e.tagKey <> "' property is not a string") (toString jTag)
4450
when (tag /= name) $
45-
Left $ decodingErr "'tag' property has an incorrect value"
46-
jValues <- mFail (decodingErr "'values' property is missing") (FO.lookup "values" jObj)
47-
values <- mFail (decodingErr "'values' property is not an array") (toArray jValues)
51+
Left $ decodingErr $ "'" <> e.tagKey <> "' property has an incorrect value"
52+
jValues <- mFail (decodingErr $ "'" <> e.valuesKey <> "' property is missing") (FO.lookup e.valuesKey jObj)
53+
values <- mFail (decodingErr $ "'" <> e.valuesKey <> "' property is not an array") (toArray jValues)
4854
{init, rest} <- lmap decodingErr $ decodeRepArgs values
4955
when (rest /= []) $
50-
Left $ decodingErr "'values' property had too many values"
56+
Left $ decodingErr $ "'" <> e.valuesKey <> "' property had too many values"
5157
pure $ Rep.Constructor init
5258

5359
class DecodeRepArgs r where
@@ -69,7 +75,11 @@ instance decodeRepArgsArgument :: (DecodeJson a) => DecodeRepArgs (Rep.Argument
6975

7076
-- | Decode `Json` representation of a value which has a `Generic` type.
7177
genericDecodeJson :: forall a r. Rep.Generic a r => DecodeRep r => Json -> Either String a
72-
genericDecodeJson = map Rep.to <<< decodeRep
78+
genericDecodeJson = genericDecodeJsonWith defaultEncoding
79+
80+
-- | Decode `Json` representation of a value which has a `Generic` type.
81+
genericDecodeJsonWith :: forall a r. Rep.Generic a r => DecodeRep r => Encoding -> Json -> Either String a
82+
genericDecodeJsonWith e = map Rep.to <<< decodeRepWith e
7383

7484
mFail :: forall a. String -> Maybe a -> Either String a
7585
mFail msg = maybe (Left msg) Right

src/Data/Argonaut/Encode/Generic/Rep.purs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ module Data.Argonaut.Encode.Generic.Rep (
44
class EncodeRepFields,
55
class EncodeLiteral,
66
encodeRep,
7+
encodeRepWith,
78
encodeRepArgs,
89
encodeRepFields,
910
genericEncodeJson,
11+
genericEncodeJsonWith,
1012
encodeLiteralSum,
1113
encodeLiteralSumWithTransform,
1214
encodeLiteral
1315
) where
1416

1517
import Prelude
18+
import Data.Argonaut.Types.Generic.Rep (Encoding, defaultEncoding)
1619

1720
import Data.Argonaut.Core (Json, fromArray, fromObject, fromString)
1821
import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson)
@@ -23,20 +26,23 @@ import Partial.Unsafe (unsafeCrashWith)
2326
import Prim.TypeError (class Fail, Text)
2427

2528
class EncodeRep r where
26-
encodeRep :: r -> Json
29+
encodeRepWith :: Encoding -> r -> Json
30+
31+
encodeRep :: forall r. EncodeRep r => r -> Json
32+
encodeRep = encodeRepWith defaultEncoding
2733

2834
instance encodeRepNoConstructors :: EncodeRep Rep.NoConstructors where
29-
encodeRep r = encodeRep r
35+
encodeRepWith e = encodeRepWith e
3036

3137
instance encodeRepSum :: (EncodeRep a, EncodeRep b) => EncodeRep (Rep.Sum a b) where
32-
encodeRep (Rep.Inl a) = encodeRep a
33-
encodeRep (Rep.Inr b) = encodeRep b
38+
encodeRepWith e (Rep.Inl a) = encodeRepWith e a
39+
encodeRepWith e (Rep.Inr b) = encodeRepWith e b
3440

3541
instance encodeRepConstructor :: (IsSymbol name, EncodeRepArgs a) => EncodeRep (Rep.Constructor name a) where
36-
encodeRep (Rep.Constructor a) =
42+
encodeRepWith e (Rep.Constructor a) =
3743
fromObject
38-
$ FO.insert "tag" (fromString (reflectSymbol (SProxy :: SProxy name)))
39-
$ FO.insert "values" (fromArray (encodeRepArgs a))
44+
$ FO.insert e.tagKey (fromString (reflectSymbol (SProxy :: SProxy name)))
45+
$ FO.insert e.valuesKey (fromArray (encodeRepArgs a))
4046
$ FO.empty
4147

4248
class EncodeRepArgs r where
@@ -61,7 +67,11 @@ instance encodeRepFieldsProduct :: (EncodeRepFields a, EncodeRepFields b) => Enc
6167

6268
-- | Encode any `Generic` data structure into `Json`.
6369
genericEncodeJson :: forall a r. Rep.Generic a r => EncodeRep r => a -> Json
64-
genericEncodeJson = encodeRep <<< Rep.from
70+
genericEncodeJson = genericEncodeJsonWith defaultEncoding
71+
72+
-- | Encode any `Generic` data structure into `Json`.
73+
genericEncodeJsonWith :: forall a r. Rep.Generic a r => EncodeRep r => Encoding -> a -> Json
74+
genericEncodeJsonWith e = encodeRepWith e <<< Rep.from
6575

6676
-- | A function for encoding `Generic` sum types using string literal representations
6777
encodeLiteralSum :: forall a r. Rep.Generic a r => EncodeLiteral r => a -> Json
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module Data.Argonaut.Types.Generic.Rep (
2+
Encoding(..),
3+
defaultEncoding
4+
) where
5+
6+
type Encoding =
7+
{ tagKey :: String
8+
, valuesKey :: String
9+
}
10+
11+
defaultEncoding :: Encoding
12+
defaultEncoding =
13+
{ tagKey: "tag"
14+
, valuesKey: "values"
15+
}
16+

test/Main.purs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import Effect (Effect)
88
import Effect.Console (log)
99
import Data.Argonaut.Core (stringify)
1010
import Data.Argonaut.Decode.Class (class DecodeJson, decodeJson)
11-
import Data.Argonaut.Decode.Generic.Rep (class DecodeLiteral, decodeLiteralSumWithTransform, genericDecodeJson)
11+
import Data.Argonaut.Decode.Generic.Rep (class DecodeLiteral, decodeLiteralSumWithTransform, genericDecodeJson, genericDecodeJsonWith)
1212
import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson)
13-
import Data.Argonaut.Encode.Generic.Rep (class EncodeLiteral, encodeLiteralSumWithTransform, genericEncodeJson)
13+
import Data.Argonaut.Encode.Generic.Rep (class EncodeLiteral, encodeLiteralSumWithTransform, genericEncodeJson, genericEncodeJsonWith)
14+
import Data.Argonaut.Types.Generic.Rep (Encoding, defaultEncoding)
1415
import Data.Argonaut.Parser (jsonParser)
1516
import Data.Either (Either(..), fromRight)
1617
import Data.Generic.Rep (class Generic)
@@ -48,6 +49,22 @@ instance encodeJsonLiteralStringExample :: EncodeJson LiteralStringExample where
4849
instance decodeJsonLiteralStringExample :: DecodeJson LiteralStringExample where
4950
decodeJson a = decodeLiteralSumWithTransform identity a
5051

52+
diffEncodingOptions :: Encoding
53+
diffEncodingOptions = defaultEncoding
54+
{ tagKey = "type"
55+
, valuesKey = "value"
56+
}
57+
58+
data DiffEncoding = A | B Int
59+
derive instance eqDiffEncoding :: Eq DiffEncoding
60+
derive instance genericDiffEncoding :: Generic DiffEncoding _
61+
instance showDiffENcoding :: Show DiffEncoding where
62+
show a = genericShow a
63+
instance encodeJsonDiffEncoding :: EncodeJson DiffEncoding where
64+
encodeJson a = genericEncodeJsonWith diffEncodingOptions a
65+
instance decodeJsonDiffEncoding :: DecodeJson DiffEncoding where
66+
decodeJson a = genericDecodeJsonWith diffEncodingOptions a
67+
5168
main :: Effect Unit
5269
main = do
5370
example $ Either $ Left "foo"
@@ -56,6 +73,8 @@ main = do
5673
example $ Nested {foo: {nested: 42}, bar: "bar"}
5774
example $ Product 1 2 $ Either $ Left "foo"
5875
example $ Frikandel
76+
example $ A
77+
example $ B 42
5978
testLiteralSumWithTransform identity Frikandel "\"Frikandel\""
6079
testLiteralSumWithTransform toUpper Frikandel "\"FRIKANDEL\""
6180
testLiteralSumWithTransform toLower Frikandel "\"frikandel\""

0 commit comments

Comments
 (0)