Skip to content

Commit b0d07f4

Browse files
Add support for decoding missing record fields to Nothing (#93)
Co-authored-by: Thomas Honeyman <[email protected]>
1 parent 3e5c1fd commit b0d07f4

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Breaking changes:
88

99
New features:
1010

11+
- Added support for decoding missing record fields to `Nothing` (#93 by @jvliwanag)
12+
1113
Bugfixes:
1214

1315
Other improvements:

src/Data/Argonaut/Decode/Class.purs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Data.String (CodePoint)
1919
import Data.Symbol (class IsSymbol, reflectSymbol)
2020
import Data.Tuple (Tuple)
2121
import Foreign.Object as FO
22-
import Prelude (class Ord, Unit, Void, bind, ($), (<<<))
22+
import Prelude (class Ord, Unit, Void, bind, ($), (<$>))
2323
import Prim.Row as Row
2424
import Prim.RowList as RL
2525
import Record as Record
@@ -111,7 +111,7 @@ instance gDecodeJsonNil :: GDecodeJson () RL.Nil where
111111
gDecodeJson _ _ = Right {}
112112

113113
instance gDecodeJsonCons
114-
:: ( DecodeJson value
114+
:: ( DecodeJsonField value
115115
, GDecodeJson rowTail tail
116116
, IsSymbol field
117117
, Row.Cons field value rowTail row
@@ -122,12 +122,27 @@ instance gDecodeJsonCons
122122
let
123123
_field = Proxy :: Proxy field
124124
fieldName = reflectSymbol _field
125+
fieldValue = FO.lookup fieldName object
125126

126-
case FO.lookup fieldName object of
127-
Just jsonVal -> do
128-
val <- lmap (AtKey fieldName) <<< decodeJson $ jsonVal
127+
case decodeJsonField fieldValue of
128+
Just fieldVal -> do
129+
val <- lmap (AtKey fieldName) fieldVal
129130
rest <- gDecodeJson object (Proxy :: Proxy tail)
130131
Right $ Record.insert _field val rest
131132

132133
Nothing ->
133134
Left $ AtKey fieldName MissingValue
135+
136+
class DecodeJsonField a where
137+
decodeJsonField :: Maybe Json -> Maybe (Either JsonDecodeError a)
138+
139+
instance decodeFieldMaybe
140+
:: DecodeJson a
141+
=> DecodeJsonField (Maybe a) where
142+
decodeJsonField Nothing = Just $ Right Nothing
143+
decodeJsonField (Just j) = Just $ decodeJson j
144+
145+
else instance decodeFieldId
146+
:: DecodeJson a
147+
=> DecodeJsonField a where
148+
decodeJsonField j = decodeJson <$> j

test/Test/Main.purs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ main = flip runReaderT 0 do
7474
suite "Encode/Decode NonEmpty Check" nonEmptyCheck
7575
suite "Encode/Decode Checks" encodeDecodeCheck
7676
suite "Encode/Decode Record Checks" encodeDecodeRecordCheck
77+
suite "Decode Optional Field Check" decodeOptionalFieldCheck
7778
suite "Combinators Checks" combinatorsCheck
7879
suite "Manual Combinators Checks" manualRecordDecode
7980
suite "Error Message Checks" errorMsgCheck
@@ -93,6 +94,27 @@ encodeDecodeRecordCheck = do
9394
let redecoded = decodeJson (encodeJson rec)
9495
pure $ Right rec == redecoded <?> (show redecoded <> " /= Right " <> show rec)
9596

97+
decodeOptionalFieldCheck :: Test
98+
decodeOptionalFieldCheck = do
99+
barMissingJson <- jsonParser' """{ }"""
100+
barNullJson <- jsonParser' """{ "bar": null }"""
101+
barPresentJson <- jsonParser' """{ "bar": [] }"""
102+
103+
test "Decode missing field" do
104+
case decodeJson barMissingJson of
105+
Right ({ bar: Nothing } :: FooRecord) -> pure unit
106+
_ -> failure ("Failed to properly decode JSON string: " <> stringify barMissingJson)
107+
108+
test "Decode null field" do
109+
case decodeJson barNullJson of
110+
Right ({ bar: Nothing } :: FooRecord) -> pure unit
111+
_ -> failure ("Failed to properly decode JSON string: " <> stringify barNullJson)
112+
113+
test "Decode present field" do
114+
case decodeJson barPresentJson of
115+
Right ({ bar: Just [] } :: FooRecord) -> pure unit
116+
_ -> failure ("Failed to properly decode JSON string: " <> stringify barPresentJson)
117+
96118
genTestJson :: Gen Json
97119
genTestJson = resize 5 genJson
98120

@@ -434,3 +456,7 @@ instance decodeJsonFooNested' :: DecodeJson FooNested' where
434456
bar <- x .:? "bar"
435457
baz <- x .:? "baz" .!= false
436458
pure $ FooNested' { bar, baz }
459+
460+
type FooRecord =
461+
{ bar :: Maybe (Array Int)
462+
}

0 commit comments

Comments
 (0)