diff --git a/FSharp.Json.Tests/Union.fs b/FSharp.Json.Tests/Union.fs index 0de36fb..9d33673 100644 --- a/FSharp.Json.Tests/Union.fs +++ b/FSharp.Json.Tests/Union.fs @@ -95,7 +95,32 @@ module Union = let actual = Json.serializeU value let expected = """{"casekey":"StringCase","casevalue":"The string"}""" Assert.AreEqual(expected, actual) - + + [] + type AsValueUnion = + | StringCase of string + | IntCase of int + + type RecordWithAsValueUnion = { + StringValue : AsValueUnion + IntValue : AsValueUnion + } + + [] + let ``Union AsValue serialization`` () = + let record = { StringValue = StringCase "String"; IntValue = IntCase 1 } + let actual = Json.serializeU record + let expected = """{"StringValue":"String","IntValue":1}""" + Assert.AreEqual(expected, actual) + + [] + let ``Union AsValue deserialization`` () = + let json = """{"StringValue":"String"}""" + let ex = Assert.Throws(fun () -> Json.deserialize json |> ignore) + Assert.IsNotNull(ex) + let expectedPath = "StringValue" + Assert.AreEqual(expectedPath, ex.Path.toString()) + [] let ``Union key-value deserialization`` () = let expected = TheAnnotatedUnion.StringCase "The string" diff --git a/FSharp.Json/Core.fs b/FSharp.Json/Core.fs index 747fc17..e4bad33 100644 --- a/FSharp.Json/Core.fs +++ b/FSharp.Json/Core.fs @@ -1,5 +1,8 @@ namespace FSharp.Json +open FSharp.Json +open FSharp.Json.Internalized.FSharp.Data + module internal Core = open System open System.Globalization @@ -248,9 +251,10 @@ module internal Core = match jsonUnion.Mode with | UnionMode.CaseKeyAsFieldName -> JsonValue.Record [| (theCase, jValue) |] | UnionMode.CaseKeyAsFieldValue -> - let jKey = (jsonUnion.CaseKeyField, JsonValue.String theCase) + let jkey = (jsonUnion.CaseKeyField, JsonValue.String theCase) let jValue = (jsonUnion.CaseValueField, jValue) - JsonValue.Record [| jKey; jValue |] + JsonValue.Record [| jkey; jValue |] + | UnionMode.AsValue -> jValue | UnionMode.CaseKeyDiscriminatorField -> match jValue with | JsonValue.Record jRecord -> @@ -519,6 +523,7 @@ module internal Core = FSharpValue.MakeUnion (caseInfo, values) | _ -> match jvalue with + | _ when jsonUnion.Mode = UnionMode.AsValue -> failDeserialization path "Failed to parse union from JSON: Union with AsValue Mode can't be parsed" | JsonValue.String caseName -> FSharpValue.MakeUnion (caseName |> getUnionCaseInfo path t, null) | JsonValue.Record fields -> @@ -550,4 +555,4 @@ module internal Core = | t when isTuple t -> deserializeTuple path t jValue | t when isUnion t -> deserializeUnion path t jValue | _ -> failDeserialization path $"Failed to serialize, must be one of following types: record, map, array, list, tuple, union. Type is: %s{t.Name}." - \ No newline at end of file + diff --git a/FSharp.Json/InterfaceTypes.fs b/FSharp.Json/InterfaceTypes.fs index c8ce7a5..8501d14 100644 --- a/FSharp.Json/InterfaceTypes.fs +++ b/FSharp.Json/InterfaceTypes.fs @@ -50,6 +50,8 @@ type UnionMode = | CaseKeyAsFieldValue = 1 /// Serialize union case key as discriminator field value. | CaseKeyDiscriminatorField = 2 + /// Serialize union case as value. + | AsValue = 3 /// Attribute customizing serialization of union types type JsonUnion () =