Skip to content

Commit af29fb9

Browse files
authored
Merge pull request #5 from garyb/more-migrations
Add some more migration codecs
2 parents c438fe8 + 1dbb945 commit af29fb9

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed
Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
1-
module Data.Codec.Argonaut.Migration where
1+
module Data.Codec.Argonaut.Migration
2+
( addDefaultField
3+
, updateField
4+
, addDefaultOrUpdateField
5+
, renameField
6+
) where
27

38
import Prelude
49

510
import Data.Argonaut.Core as J
611
import Data.Codec (basicCodec)
712
import Data.Codec.Argonaut (JsonCodec)
8-
import Data.Maybe (Maybe(..), maybe)
13+
import Data.Maybe (Maybe(..), maybe, fromMaybe)
914
import Data.Tuple (uncurry)
1015
import Data.StrMap as SM
1116

1217
-- | When dealing with a JSON object that may be missing a field, this codec
1318
-- | can be used to alter the JSON before parsing to ensure a default value is
1419
-- | present instead.
1520
addDefaultField String J.Json JsonCodec J.Json
16-
addDefaultField field defaultValue = basicCodec (pure <<< dec) id
17-
where
18-
dec J.Json J.Json
19-
dec j = J.foldJsonObject j (J.fromObject <<< setDefault) j
20-
setDefault J.JObject J.JObject
21-
setDefault = SM.alter (maybe (Just defaultValue) Just) field
21+
addDefaultField field = addDefaultOrUpdateField field <<< fromMaybe
22+
23+
-- | Re-maps the value of a field in a JSON object.
24+
updateField String (J.Json J.Json) JsonCodec J.Json
25+
updateField field = alterField field <<< map
26+
27+
-- | When dealing with a JSON object that may be missing a field, this codec
28+
-- | can be used to alter the JSON before parsing to ensure a default value is
29+
-- | present instead. Similar to `addDefaultField`, but allows existing values
30+
-- | to be modified also.
31+
addDefaultOrUpdateField String (Maybe J.Json J.Json) JsonCodec J.Json
32+
addDefaultOrUpdateField field = alterField field <<< map Just
2233

2334
-- | When dealing with a JSON object that has had a field name changed, this
2435
-- | codec can be used to alter the JSON before parsing to ensure the new field
@@ -30,3 +41,11 @@ renameField oldName newName = basicCodec (pure <<< dec) id
3041
dec j = J.foldJsonObject j (J.fromObject <<< rename) j
3142
rename J.JObject J.JObject
3243
rename obj = maybe obj (uncurry (SM.insert newName)) (SM.pop oldName obj)
44+
45+
alterField String (Maybe J.Json Maybe J.Json) JsonCodec J.Json
46+
alterField field f = basicCodec (pure <<< dec) id
47+
where
48+
dec J.Json J.Json
49+
dec j = J.foldJsonObject j (J.fromObject <<< setDefault) j
50+
setDefault J.JObject J.JObject
51+
setDefault = SM.alter f field

test/Test/Migration.purs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Data.Codec ((<~<))
88
import Data.Codec.Argonaut.Common as JA
99
import Data.Codec.Argonaut.Migration as JAM
1010
import Data.Either (Either(..))
11-
import Data.Maybe (Maybe(..))
11+
import Data.Maybe (Maybe(..), fromMaybe, maybe)
1212
import Data.String.Gen (genAsciiString)
1313
import Data.StrMap as SM
1414
import Test.QuickCheck (Result(..), QC, quickCheck, (===))
@@ -23,6 +23,15 @@ main = do
2323
log "Checking addDefaultField preserves an existing value if it's already present"
2424
quickCheck propDefaultFieldPreservesOriginal
2525

26+
log "Checking updateField updates an existing value if it's already present"
27+
quickCheck propUpdateFieldAltersOriginal
28+
29+
log "Checking addDefaultOrUpdateField adds a field if it is missing"
30+
quickCheck propAddDefaultOrUpdateField
31+
32+
log "Checking addDefaultOrUpdateField updates an existing value if it's already present"
33+
quickCheck propAddDefaultOrUpdateFieldAltersOriginal
34+
2635
log "Checking renameField renames a field"
2736
quickCheck propDefaultFieldPreservesOriginal
2837

@@ -43,6 +52,32 @@ propDefaultFieldPreservesOriginal = do
4352
pure $ testMigrationCodec { key: missingKey, expectedValue, input }
4453
$ JA.jobject <~< JAM.addDefaultField missingKey unexpectedValue
4554

55+
propUpdateFieldAltersOriginal Gen Result
56+
propUpdateFieldAltersOriginal = do
57+
let expectedValue = J.fromString "it's here"
58+
let unexpectedValue = J.fromString "it shouldn't be here"
59+
updateKey ← genAsciiString
60+
input ← SM.insert updateKey unexpectedValue <$> genJObject
61+
pure $ testMigrationCodec { key: updateKey, expectedValue, input }
62+
$ JA.jobject <~< JAM.updateField updateKey (const expectedValue)
63+
64+
propAddDefaultOrUpdateField Gen Result
65+
propAddDefaultOrUpdateField = do
66+
let expectedValue = J.fromString "it's here"
67+
missingKey ← genAsciiString
68+
input ← SM.delete missingKey <$> genJObject
69+
pure $ testMigrationCodec { key: missingKey, expectedValue, input }
70+
$ JA.jobject <~< JAM.addDefaultOrUpdateField missingKey (fromMaybe expectedValue)
71+
72+
propAddDefaultOrUpdateFieldAltersOriginal Gen Result
73+
propAddDefaultOrUpdateFieldAltersOriginal = do
74+
let expectedValue = J.fromString "it's here"
75+
let unexpectedValue = J.fromString "it shouldn't be here"
76+
updateKey ← genAsciiString
77+
input ← SM.insert updateKey unexpectedValue <$> genJObject
78+
pure $ testMigrationCodec { key: updateKey, expectedValue, input }
79+
$ JA.jobject <~< JAM.addDefaultOrUpdateField updateKey (maybe unexpectedValue (const expectedValue))
80+
4681
propRenameField Gen Result
4782
propRenameField = do
4883
let expectedValue = J.fromString "it's here"

0 commit comments

Comments
 (0)