@@ -3,6 +3,7 @@ module Data.Codec.Argonaut.Migration
3
3
, updateField
4
4
, addDefaultOrUpdateField
5
5
, renameField
6
+ , nestForTagged
6
7
) where
7
8
8
9
import Prelude
@@ -11,8 +12,9 @@ import Data.Argonaut.Core as J
11
12
import Data.Codec (basicCodec )
12
13
import Data.Codec.Argonaut (JsonCodec )
13
14
import Data.Maybe (Maybe (..), maybe , fromMaybe )
14
- import Data.Tuple (uncurry )
15
15
import Data.StrMap as SM
16
+ import Data.StrMap.ST as SMST
17
+ import Data.Tuple (Tuple (..), uncurry )
16
18
17
19
-- | When dealing with a JSON object that may be missing a field, this codec
18
20
-- | can be used to alter the JSON before parsing to ensure a default value is
@@ -42,6 +44,46 @@ renameField oldName newName = basicCodec (pure <<< dec) id
42
44
rename ∷ J.JObject → J.JObject
43
45
rename obj = maybe obj (uncurry (SM .insert newName)) (SM .pop oldName obj)
44
46
47
+ -- | Prepares an object from a legacy codec for use in a `Variant` or
48
+ -- | `taggedSum` codec.
49
+ -- |
50
+ -- | For an input like:
51
+ -- | ```{ "tag": "tag", "x": 1, "y": 2, "z": 3 }```
52
+ -- | the result will be:
53
+ -- | ```{ "tag": "tag", "value": { "x": 1, "y": 2, "z": 3 } }```
54
+ -- |
55
+ -- | For an input like:
56
+ -- | ```{ "tag": "tag", "value": 1, "foo": 2 }```
57
+ -- | the result will be:
58
+ -- | ```{ "tag": "tag", "value": { "value": 1, "foo": 2 }```
59
+ -- |
60
+ -- | If the value is already in the expected form, where there is only `value`
61
+ -- | and no other keys (aside from `tag`):
62
+ -- | ```{ "tag": "tag", "value": true }```
63
+ -- | the result will be the same as the input.
64
+ -- |
65
+ -- | If the tag field is missing from the input, it will also be missing in the
66
+ -- | output.
67
+ nestForTagged ∷ JsonCodec J.Json
68
+ nestForTagged = basicCodec (pure <<< dec) id
69
+ where
70
+ dec ∷ J.Json → J.Json
71
+ dec j = J .foldJsonObject j (J .fromObject <<< rewrite) j
72
+ rewrite ∷ J.JObject → J.JObject
73
+ rewrite obj =
74
+ case SM .pop " tag" obj of
75
+ Nothing → SM .pureST do
76
+ result ← SMST .new
77
+ SMST .poke result " value" (mkValue obj)
78
+ Just (Tuple tagValue obj') → SM .pureST do
79
+ result ← SMST .new
80
+ _ ← SMST .poke result " tag" tagValue
81
+ SMST .poke result " value" (mkValue obj')
82
+ mkValue ∷ J.JObject → J.Json
83
+ mkValue obj = case SM .pop " value" obj of
84
+ Just (Tuple valueValue obj') | SM .isEmpty obj' → valueValue
85
+ _ → J .fromObject obj
86
+
45
87
alterField ∷ String → (Maybe J.Json → Maybe J.Json ) → JsonCodec J.Json
46
88
alterField field f = basicCodec (pure <<< dec) id
47
89
where
0 commit comments