@@ -371,3 +371,118 @@ module ``Unmatched case handling`` =
371
371
&& string jo.[ " case" ]= " CaseUnknown" @>
372
372
let expected = " {\r\n \" case\" : \" CaseUnknown\" ,\r\n \" a\" : \" s\" ,\r\n \" b\" : 1,\r\n \" c\" : true\r\n }" .Replace( " \r\n " , Environment.NewLine)
373
373
test <@ expected = string jo @>
374
+
375
+ module Nested =
376
+
377
+ [<JsonConverter( typeof< UnionConverter>) >]
378
+ type U =
379
+ | B of NU
380
+ | C of UUA
381
+ | D of UU
382
+ | E of E
383
+ | EA of E []
384
+ | R of {| a : int ; b : NU |}
385
+ | S
386
+ and [<JsonConverter(typeof<UnionConverter>)>]
387
+ NU =
388
+ | A of string
389
+ | B of int
390
+ | R of {| a : int ; b : NU |}
391
+ | S
392
+ and [<JsonConverter(typeof<UnionConverter>)>]
393
+ UU =
394
+ | A of string
395
+ | B of int
396
+ | E of E
397
+ | EO of E option
398
+ | R of {| a: int ; b: string |}
399
+ | S
400
+ and [<JsonConverter(typeof<UnionConverter>, "case2")>]
401
+ UUA =
402
+ | A of string
403
+ | B of int
404
+ | E of E
405
+ | EO of E option
406
+ | R of {| a: int ; b: string |}
407
+ | S
408
+ and [<JsonConverter(typeof<TypeSafeEnumConverter>)>]
409
+ E =
410
+ | V1
411
+ | V2
412
+
413
+ let [<FsCheck.Xunit.Property>] ``can nest`` ( value : U ) =
414
+ let ser = Serdes.Serialize value
415
+ test <@ value = Serdes.Deserialize ser @>
416
+
417
+ let [<Fact>] ``nesting Unions represents child as item`` () =
418
+ let v : U = U.C( UUA.B 42 )
419
+ let ser = Serdes.Serialize v
420
+ """ {"case":"C","Item":{"case2":"B","Item":42}}""" =! ser
421
+ test <@ v = Serdes.Deserialize ser @>
422
+
423
+ let [<Fact>] ``TypeSafeEnum converts direct`` () =
424
+ let v : U = U.C ( UUA.E E.V1)
425
+ let ser = Serdes.Serialize v
426
+ """ {"case":"C","Item":{"case2":"E","Item":"V1"}}""" =! ser
427
+ test <@ v = Serdes.Deserialize ser @>
428
+
429
+ let v : U = U.E E.V2
430
+ let ser = Serdes.Serialize v
431
+ """ {"case":"E","Item":"V2"}""" =! ser
432
+ test <@ v = Serdes.Deserialize ser @>
433
+
434
+ let v : U = U.EA [| E.V2; E.V2|]
435
+ let ser = Serdes.Serialize v
436
+ """ {"case":"EA","Item":["V2","V2"]}""" =! ser
437
+ test <@ v = Serdes.Deserialize ser @>
438
+
439
+ let v : U = U.C ( UUA.EO ( Some E.V1))
440
+ let ser = Serdes.Serialize v
441
+ """ {"case":"C","Item":{"case2":"EO","Item":"V1"}}""" =! ser
442
+ test <@ v = Serdes.Deserialize ser @>
443
+
444
+ let v : U = U.C ( UUA.EO None)
445
+ let ser = Serdes.Serialize v
446
+ """ {"case":"C","Item":{"case2":"EO","Item":null}}""" =! ser
447
+ test <@ v = Serdes.Deserialize ser @>
448
+
449
+ let v : U = U.C UUA.S
450
+ let ser = Serdes.Serialize v
451
+ """ {"case":"C","Item":{"case2":"S"}}""" =! ser
452
+ test <@ v = Serdes.Deserialize ser @>
453
+
454
+ /// And for everything else, JsonIsomorphism allows plenty ways of customizing the encoding and/or decoding
455
+ module IsomorphismUnionEncoder =
456
+
457
+ type [<JsonConverter( typeof< TopConverter>) >]
458
+ Top =
459
+ | S
460
+ | N of Nested
461
+ and Nested =
462
+ | A
463
+ | B of int
464
+ and TopConverter () =
465
+ inherit JsonIsomorphism< Top, Flat< int>>()
466
+ override __.Pickle value =
467
+ match value with
468
+ | S -> { disc = TS; v = None }
469
+ | N A -> { disc = TA; v = None }
470
+ | N ( B v) -> { disc = TB; v = Some v }
471
+ override __.UnPickle flat =
472
+ match flat with
473
+ | { disc = TS } -> S
474
+ | { disc = TA } -> N A
475
+ | { disc = TB; v = v} -> N ( B ( Option.get v))
476
+ and Flat < 'T > = { disc : JiType ; v : 'T option }
477
+ and [<JsonConverter(typeof<TypeSafeEnumConverter>)>]
478
+ JiType = TS | TA | TB
479
+
480
+ let [<Fact>] ``Can control the encoding to the nth degree`` () =
481
+ let v : Top = N ( B 42 )
482
+ let ser = Serdes.Serialize v
483
+ """ {"disc":"TB","v":42}""" =! ser
484
+ test <@ v = Serdes.Deserialize ser @>
485
+
486
+ let [<FsCheck.Xunit.Property>] ``can roundtrip`` ( value : Top ) =
487
+ let ser = Serdes.Serialize value
488
+ test <@ value = Serdes.Deserialize ser @>
0 commit comments