diff --git a/FSharp.Json.Tests/Union.fs b/FSharp.Json.Tests/Union.fs index 1573d8b..6e55f2a 100644 --- a/FSharp.Json.Tests/Union.fs +++ b/FSharp.Json.Tests/Union.fs @@ -9,7 +9,7 @@ module Union = type TheUnion = | OneFieldCase of string - | ManyFieldsCase of string*int + | ManyFieldsCase of field1:string*field2:int | RecordCase of TheRecord [] @@ -19,6 +19,13 @@ module Union = let expected = """{"OneFieldCase":"The string"}""" Assert.AreEqual(expected, actual) + [] + let ``Union two field case serialization`` () = + let value = ManyFieldsCase("The string", 2) + let actual = Json.serializeU value + let expected = """{"ManyFieldsCase":{"field1":"The string","field2":2}}""" + Assert.AreEqual(expected, actual) + [] let ``Union one field case deserialization`` () = let expected = OneFieldCase "The string" @@ -26,6 +33,13 @@ module Union = let actual = Json.deserialize json Assert.AreEqual(expected, actual) + [] + let ``Union two field case deserialization`` () = + let expected = ManyFieldsCase("The string", 2) + let json = Json.serialize(expected) + let actual = Json.deserialize json + Assert.AreEqual(expected, actual) + [] let ``Union many fields case serialization`` () = let expected = ManyFieldsCase ("The string", 123) diff --git a/FSharp.Json/Core.fs b/FSharp.Json/Core.fs index 6119bbd..2c7bf33 100644 --- a/FSharp.Json/Core.fs +++ b/FSharp.Json/Core.fs @@ -229,7 +229,9 @@ module internal Core = let caseType = types.[0] serializeUnwrapOptionWithNull caseType jsonField caseValue | _ -> - serializeTupleItems types values + let props: PropertyInfo array = caseInfo.GetFields() + let fields = props |> Array.map (serializeProperty theunion) |> Array.choose id + JsonValue.Record fields let unionCases = getUnionCases caseInfo.DeclaringType match unionCases.Length with | 1 -> jvalue @@ -519,7 +521,17 @@ module internal Core = [| propValue |] | _ -> let propsTypes = props |> Array.map (fun p -> p.PropertyType) - deserializeTupleElements casePath propsTypes fieldValue + match fieldValue with + | JsonValue.Record(jsonFields) -> + let fields = jsonFields |> Map.ofArray + props + |> Array.map(fun prop -> + match prop.Name |> fields.TryFind with + | Some value -> + deserializeUnwrapOption path prop.PropertyType JsonField.Default (Some value) + | None -> failDeserialization path "Failed to parse union from JSON because field %s of case %s is missing." prop.Name caseInfo.Name + ) + | _ -> failDeserialization path "Failed to parse union from JSON that is not object." FSharpValue.MakeUnion (caseInfo, values) | _ -> failDeserialization path "Failed to parse union from JSON that is not object." diff --git a/FSharp.Json/Interface.fs b/FSharp.Json/Interface.fs index 4f89d65..3fa6342 100644 --- a/FSharp.Json/Interface.fs +++ b/FSharp.Json/Interface.fs @@ -39,6 +39,11 @@ module Json = let value = JsonValue.Parse(json) (Core.deserialize config JsonPath.Root typeof<'T> value) :?> 'T + let deserializeExDynamic (typ: Type) (config: JsonConfig) (json: string): obj = + let value = JsonValue.Parse(json) + Core.deserialize config JsonPath.Root typ value + + /// Serailizes F# object into JSON. Uses default [JsonConfig]. let serialize (theobj: obj) = serializeEx JsonConfig.Default theobj @@ -49,3 +54,6 @@ module Json = /// Deserailizes JSON into F# type provided as generic parameter. Uses default [JsonConfig]. let deserialize<'T> (json: string) = deserializeEx<'T> JsonConfig.Default json + + /// Deserailizes JSON into F# type provided as generic parameter. Uses default [JsonConfig]. + let deserializeDynamic typ (json: string) = deserializeExDynamic typ JsonConfig.Default json