Skip to content

Commit 56583cb

Browse files
committed
mapTag for flat encoding
1 parent 26bba8f commit 56583cb

File tree

2 files changed

+84
-65
lines changed

2 files changed

+84
-65
lines changed

src/Data/Codec/Argonaut/Sum.purs

Lines changed: 34 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -415,27 +415,31 @@ encodeSumCase encoding rawTag jsons =
415415

416416
type FlatEncoding (tagSymbol) =
417417
{ tag Proxy tag
418+
, mapTag String String
418419
}
419420

420421
defaultFlatEncoding FlatEncoding "tag"
421-
defaultFlatEncoding = { tag: Proxy }
422+
defaultFlatEncoding =
423+
{ tag: Proxy
424+
, mapTag: identity
425+
}
422426

423427
sumFlat r rep a. GFlatCases "tag" r rep Generic a rep String Record r JsonCodec a
424428
sumFlat = sumFlatWith defaultFlatEncoding
425429

426430
sumFlatWith @tag r rep a. GFlatCases tag r rep Generic a rep FlatEncoding tag String Record r JsonCodec a
427-
sumFlatWith _ name r =
431+
sumFlatWith encoding name r =
428432
dimap from to $ codec' dec enc
429433
where
430-
dec = gFlatCasesDecode @tag r >>> (lmap $ Named name)
431-
enc = gFlatCasesEncode @tag r
434+
dec = gFlatCasesDecode @tag encoding r >>> (lmap $ Named name)
435+
enc = gFlatCasesEncode @tag encoding r
432436

433437
class GFlatCasesSymbol Row Type Type Constraint
434438
class
435439
GFlatCases tag r rep
436440
where
437-
gFlatCasesEncode Record r rep Json
438-
gFlatCasesDecode Record r Json Either JsonDecodeError rep
441+
gFlatCasesEncode FlatEncoding tag Record r rep Json
442+
gFlatCasesDecode FlatEncoding tag Record r Json Either JsonDecodeError rep
439443

440444
instance gFlatCasesConstructorNoArg
441445
( Row.Cons name Unit () rc
@@ -444,22 +448,23 @@ instance gFlatCasesConstructorNoArg ∷
444448
, IsSymbol tag
445449
)
446450
GFlatCases tag rc (Constructor name NoArguments) where
447-
gFlatCasesEncode Record rc Constructor name NoArguments Json
448-
gFlatCasesEncode _ (Constructor NoArguments) =
451+
gFlatCasesEncode FlatEncoding tag Record rc Constructor name NoArguments Json
452+
gFlatCasesEncode { mapTag } _ (Constructor NoArguments) =
449453
let
450-
name = reflectSymbol (Proxy @name) String
454+
nameRaw = reflectSymbol (Proxy @name) String
455+
name = mapTag nameRaw String
451456
propCodec = CAR.record {} JPropCodec {}
452457
propCodecWithTag = CA.recordProp (Proxy @tag) CA.string propCodec JPropCodec (Record rf)
453458
codecWithTag = CA.object ("case " <> name) propCodecWithTag JsonCodec (Record rf)
454459
rcWithTag = Record.insert (Proxy @tag) name {} Record rf
455460
in
456461
CA.encode codecWithTag rcWithTag
457462

458-
gFlatCasesDecode Record rc Json Either JsonDecodeError (Constructor name NoArguments)
459-
gFlatCasesDecode _ json = do
463+
gFlatCasesDecode FlatEncoding tag Record rc Json Either JsonDecodeError (Constructor name NoArguments)
464+
gFlatCasesDecode { mapTag } _ json = do
460465
let
461-
name = reflectSymbol (Proxy @name) String
462-
466+
nameRaw = reflectSymbol (Proxy @name) String
467+
name = mapTag nameRaw String
463468
propCodec = CAR.record {} JPropCodec {}
464469
propCodecWithTag = CA.recordProp (Proxy @tag) CA.string propCodec JPropCodec (Record rf)
465470
codecWithTag = CA.object ("case " <> name) propCodecWithTag JsonCodec (Record rf)
@@ -480,21 +485,23 @@ instance gFlatCasesConstructorSingleArg ∷
480485
, IsSymbol tag
481486
)
482487
GFlatCases tag rc (Constructor name (Argument (Record rf))) where
483-
gFlatCasesEncode Record rc Constructor name (Argument (Record rf)) Json
484-
gFlatCasesEncode rc (Constructor (Argument rf)) =
488+
gFlatCasesEncode FlatEncoding tag Record rc Constructor name (Argument (Record rf)) Json
489+
gFlatCasesEncode { mapTag } rc (Constructor (Argument rf)) =
485490
let
486-
name = reflectSymbol (Proxy @name) String
491+
nameRaw = reflectSymbol (Proxy @name) String
492+
name = mapTag nameRaw String
487493
propCodec = Record.get (Proxy @name) rc JPropCodec (Record rf)
488494
propCodecWithTag = CA.recordProp (Proxy @tag) CA.string propCodec JPropCodec (Record rf')
489495
codecWithTag = CA.object ("case " <> name) propCodecWithTag JsonCodec (Record rf')
490496
rcWithTag = Record.insert (Proxy @tag) name rf Record rf'
491497
in
492498
CA.encode codecWithTag rcWithTag
493499

494-
gFlatCasesDecode Record rc Json Either JsonDecodeError (Constructor name (Argument (Record rf)))
495-
gFlatCasesDecode rc json = do
500+
gFlatCasesDecode FlatEncoding tag Record rc Json Either JsonDecodeError (Constructor name (Argument (Record rf)))
501+
gFlatCasesDecode { mapTag } rc json = do
496502
let
497-
name = reflectSymbol (Proxy @name) String
503+
nameRaw = reflectSymbol (Proxy @name) String
504+
name = mapTag nameRaw String
498505
propCodec = Record.get (Proxy @name) rc JPropCodec (Record rf)
499506
propCodecWithTag = CA.recordProp (Proxy @tag) CA.string propCodec JPropCodec (Record rf')
500507
codecWithTag = CA.object ("case " <> name) propCodecWithTag JsonCodec (Record rf')
@@ -518,61 +525,30 @@ instance gFlatCasesSum ∷
518525
, IsSymbol name
519526
)
520527
GFlatCases tag r (Sum (Constructor name lhs) rhs) where
521-
gFlatCasesEncode Record r Sum (Constructor name lhs) rhs Json
522-
gFlatCasesEncode r =
528+
gFlatCasesEncode FlatEncoding tag Record r Sum (Constructor name lhs) rhs Json
529+
gFlatCasesEncode encoding r =
523530
let
524531
codec = Record.get (Proxy @name) r codec
525532
r1 = Record.insert (Proxy @name) codec {} Record r1
526533
r2 = unsafeDelete (Proxy @name) r Record r2
527534
in
528535
case _ of
529-
Inl lhs → gFlatCasesEncode @tag r1 lhs
530-
Inr rhs → gFlatCasesEncode @tag r2 rhs
536+
Inl lhs → gFlatCasesEncode @tag encoding r1 lhs
537+
Inr rhs → gFlatCasesEncode @tag encoding r2 rhs
531538

532-
gFlatCasesDecode Record r Json Either JsonDecodeError (Sum (Constructor name lhs) rhs)
533-
gFlatCasesDecode r tagged = do
539+
gFlatCasesDecode FlatEncoding tag Record r Json Either JsonDecodeError (Sum (Constructor name lhs) rhs)
540+
gFlatCasesDecode encoding r tagged = do
534541
let
535542
codec = Record.get (Proxy @name) r codec
536543
r1 = Record.insert (Proxy @name) codec {} Record r1
537544
r2 = Record.delete (Proxy @name) r Record r2
538545
let
539-
lhs = gFlatCasesDecode @tag r1 tagged _ (Constructor name lhs)
540-
rhs = gFlatCasesDecode @tag r2 tagged _ rhs
546+
lhs = gFlatCasesDecode @tag encoding r1 tagged _ (Constructor name lhs)
547+
rhs = gFlatCasesDecode @tag encoding r2 tagged _ rhs
541548
(Inl <$> lhs) <|> (Inr <$> rhs)
542549

543550
--------------------------------------------------------------------------------
544551

545-
sumEnum r rep a. GEnumCases r rep Generic a rep String Record r JsonCodec a
546-
sumEnum = unsafeCoerce 1
547-
548-
class GEnumCasesRow Type Type Constraint
549-
class
550-
GEnumCases r rep
551-
where
552-
gEnumCasesEncode Record r rep Json
553-
gEnumCasesDecode Record r Json Either JsonDecodeError rep
554-
555-
instance gEnumCasesConstructorNoArg
556-
( Row.Cons name Unit () rc
557-
, IsSymbol name
558-
)
559-
GEnumCases rc (Constructor name NoArguments) where
560-
gEnumCasesEncode Record rc Constructor name NoArguments Json
561-
gEnumCasesEncode _ _ =
562-
let
563-
name = reflectSymbol (Proxy @name) String
564-
in
565-
encodeSumCase defaultEncoding name []
566-
567-
gEnumCasesDecode Record rc Json Either JsonDecodeError (Constructor name NoArguments)
568-
gEnumCasesDecode _ json = do
569-
let name = reflectSymbol (Proxy @name) String
570-
571-
parseNoFields defaultEncoding json name
572-
pure $ Constructor NoArguments
573-
574-
--------------------------------------------------------------------------------
575-
576552
-- | Same as `Record.delete` but deleting only happens at the type level
577553
-- | and the value is left untouched.
578554
unsafeDelete r1 r2 l a. IsSymbol l Row.Lacks l r1 Row.Cons l a r1 r2 Proxy l Record r2 Record r1

test/Test/Sum.purs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Data.Codec (decode, encode)
1010
import Data.Codec.Argonaut (JsonCodec)
1111
import Data.Codec.Argonaut as C
1212
import Data.Codec.Argonaut.Record as CR
13-
import Data.Codec.Argonaut.Sum (Encoding(..), defaultEncoding, sumFlatWith, sumWith)
13+
import Data.Codec.Argonaut.Sum (Encoding(..), FlatEncoding, defaultEncoding, sumFlatWith, sumWith)
1414
import Data.Generic.Rep (class Generic)
1515
import Data.Show.Generic (genericShow)
1616
import Data.String as Str
@@ -66,8 +66,8 @@ instance Arbitrary SampleFlat where
6666
instance Show SampleFlat where
6767
show = genericShow
6868

69-
codecSampleFlat JsonCodec SampleFlat
70-
codecSampleFlat = sumFlatWith { tag: Proxy @"tag" } "Sample"
69+
codecSampleFlat FlatEncoding "tag" JsonCodec SampleFlat
70+
codecSampleFlat encoding = sumFlatWith encoding "Sample"
7171
{ "FlatFoo": unit
7272
, "FlatBar": CR.record { errors: C.int }
7373
, "FlatBaz": CR.record
@@ -445,22 +445,29 @@ main = do
445445

446446
log "Check sum flat"
447447
do
448-
check codecSampleFlat FlatFoo
448+
log " - Custom tag"
449+
let
450+
opts =
451+
{ tag: Proxy @"tag"
452+
, mapTag: identity
453+
}
454+
455+
check (codecSampleFlat opts) FlatFoo
449456
$ Str.joinWith "\n"
450457
[ "{"
451458
, " \"tag\": \"FlatFoo\""
452459
, "}"
453460
]
454461

455-
check codecSampleFlat (FlatBar { errors: 42 })
462+
check (codecSampleFlat opts) (FlatBar { errors: 42 })
456463
$ Str.joinWith "\n"
457464
[ "{"
458465
, " \"tag\": \"FlatBar\","
459466
, " \"errors\": 42"
460467
, "}"
461468
]
462469

463-
check codecSampleFlat (FlatBaz { active: true, name: "hello", pos: { x: 42, y: 42 } })
470+
check (codecSampleFlat opts) (FlatBaz { active: true, name: "hello", pos: { x: 42, y: 42 } })
464471
$ Str.joinWith "\n"
465472
[ "{"
466473
, " \"tag\": \"FlatBaz\","
@@ -473,5 +480,41 @@ main = do
473480
, "}"
474481
]
475482

476-
quickCheck (propCodec arbitrary codecSampleFlat)
483+
do
484+
log " - mapTag"
485+
let
486+
opts =
487+
{ tag: Proxy @"tag"
488+
, mapTag: Str.toLower
489+
}
490+
491+
check (codecSampleFlat opts) FlatFoo
492+
$ Str.joinWith "\n"
493+
[ "{"
494+
, " \"tag\": \"flatfoo\""
495+
, "}"
496+
]
497+
498+
check (codecSampleFlat opts) (FlatBar { errors: 42 })
499+
$ Str.joinWith "\n"
500+
[ "{"
501+
, " \"tag\": \"flatbar\","
502+
, " \"errors\": 42"
503+
, "}"
504+
]
505+
506+
check (codecSampleFlat opts) (FlatBaz { active: true, name: "hello", pos: { x: 42, y: 42 } })
507+
$ Str.joinWith "\n"
508+
[ "{"
509+
, " \"tag\": \"flatbaz\","
510+
, " \"active\": true,"
511+
, " \"name\": \"hello\","
512+
, " \"pos\": {"
513+
, " \"x\": 42,"
514+
, " \"y\": 42"
515+
, " }"
516+
, "}"
517+
]
518+
519+
quickCheck (propCodec arbitrary (codecSampleFlat opts))
477520

0 commit comments

Comments
 (0)