@@ -23,6 +23,7 @@ module Data.Codec.Argonaut
2323 , record
2424 , recordProp
2525 , recordPropOptional
26+ , recordPropOptionalWith
2627 , fix
2728 , named
2829 , coercible
@@ -32,6 +33,7 @@ module Data.Codec.Argonaut
3233
3334import Prelude
3435
36+ import Data.Argonaut.Core (Json )
3537import Data.Argonaut.Core as J
3638import Data.Array as A
3739import Data.Bifunctor (bimap , lmap )
@@ -41,7 +43,7 @@ import Data.Codec (Codec(..), Codec', codec, codec', decode, encode, hoist, iden
4143import Data.Either (Either (..), note )
4244import Data.Generic.Rep (class Generic )
4345import Data.Int as I
44- import Data.List ((:))
46+ import Data.List (List , (:))
4547import Data.List as L
4648import Data.Maybe (Maybe (..), maybe )
4749import Data.String as S
@@ -52,7 +54,8 @@ import Data.Tuple (Tuple(..))
5254import Foreign.Object as FO
5355import Prim.Coerce (class Coercible )
5456import Prim.Row as Row
55- import Record.Unsafe as Record
57+ import Record as Record
58+ import Record.Unsafe as RecordUnsafe
5659import Safe.Coerce (coerce )
5760import Type.Proxy (Proxy )
5861import Unsafe.Coerce (unsafeCoerce )
@@ -264,11 +267,11 @@ recordProp p codecA codecR =
264267 a ← BF .lmap (AtKey key) case FO .lookup key obj of
265268 Just val → Codec .decode codecA val
266269 Nothing → Left MissingValue
267- pure $ Record .unsafeSet key a r
270+ pure $ RecordUnsafe .unsafeSet key a r
268271
269272 enc' ∷ String → Record r' → L.List (Tuple String J.Json )
270273 enc' key val =
271- Tuple key (Codec .encode codecA (Record .unsafeGet key val))
274+ Tuple key (Codec .encode codecA (RecordUnsafe .unsafeGet key val))
272275 : Codec .encode codecR (unsafeForget val)
273276
274277 unsafeForget ∷ Record r' → Record r
@@ -300,18 +303,58 @@ recordPropOptional p codecA codecR = Codec.codec dec' enc'
300303 a ← BF .lmap (AtKey key) case FO .lookup key obj of
301304 Just val → Just <$> Codec .decode codecA val
302305 _ → Right Nothing
303- pure $ Record .unsafeSet key a r
306+ pure $ RecordUnsafe .unsafeSet key a r
304307
305308 enc' ∷ Record r' → L.List (Tuple String J.Json )
306309 enc' val = do
307310 let w = Codec .encode codecR (unsafeForget val)
308- case Record .unsafeGet key val of
311+ case RecordUnsafe .unsafeGet key val of
309312 Just a → Tuple key (Codec .encode codecA a) : w
310313 Nothing → w
311314
312315 unsafeForget ∷ Record r' → Record r
313316 unsafeForget = unsafeCoerce
314317
318+ recordPropOptionalWith
319+ ∷ ∀ p a b r r'
320+ . IsSymbol p
321+ ⇒ Row.Cons p b r r'
322+ ⇒ Row.Lacks p r
323+ ⇒ Proxy p
324+ → (Maybe a → b )
325+ → (b → a )
326+ → JsonCodec a
327+ → JPropCodec (Record r )
328+ → JPropCodec (Record r' )
329+ recordPropOptionalWith p normalize denormalize codecA codecR = Codec .codec dec' enc'
330+ where
331+ key ∷ String
332+ key = reflectSymbol p
333+
334+ dec' ∷ FO.Object J.Json → Either JsonDecodeError (Record r' )
335+ dec' obj = do
336+ r ∷ Record r ← Codec.decode codecR obj
337+ b ∷ b ← BF.lmap (AtKey key ) case FO.lookup key obj of
338+ Just j → do
339+ ret ∷ a ← Codec.decode codecA j
340+ pure $ normalize (Just ret )
341+ Nothing → pure $ normalize Nothing
342+ pure $ Record .insert p b r
343+
344+ enc' ∷ Record r' → L.List (Tuple String J.Json )
345+ enc' val = do
346+ let
347+ w ∷ List (Tuple String Json )
348+ w = Codec .encode codecR (unsafeForget val)
349+
350+ b ∷ b
351+ b = Record .get p val
352+
353+ Tuple key (Codec .encode codecA $ denormalize b) : w
354+
355+ unsafeForget ∷ Record r' → Record r
356+ unsafeForget = unsafeCoerce
357+
315358jsonPrimCodec ∷ ∀ a . String → (J.Json → Maybe a ) → (a → J.Json ) → JsonCodec a
316359jsonPrimCodec ty f = Codec .codec' (maybe (Left (TypeMismatch ty)) pure <<< f)
317360
0 commit comments