@@ -371,3 +371,118 @@ module ``Unmatched case handling`` =
371371 && string jo.[ " case" ]= " CaseUnknown" @>
372372 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)
373373 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