Skip to content

Add new UnionMode #58

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion FSharp.Json.Tests/Union.fs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,32 @@ module Union =
let actual = Json.serializeU value
let expected = """{"casekey":"StringCase","casevalue":"The string"}"""
Assert.AreEqual(expected, actual)


[<JsonUnion(Mode = UnionMode.AsValue)>]
type AsValueUnion =
| StringCase of string
| IntCase of int

type RecordWithAsValueUnion = {
StringValue : AsValueUnion
IntValue : AsValueUnion
}

[<Test>]
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)

[<Test>]
let ``Union AsValue deserialization`` () =
let json = """{"StringValue":"String"}"""
let ex = Assert.Throws<JsonDeserializationError>(fun () -> Json.deserialize<RecordWithAsValueUnion> json |> ignore)
Assert.IsNotNull(ex)
let expectedPath = "StringValue"
Assert.AreEqual(expectedPath, ex.Path.toString())

[<Test>]
let ``Union key-value deserialization`` () =
let expected = TheAnnotatedUnion.StringCase "The string"
Expand Down
5 changes: 5 additions & 0 deletions FSharp.Json/Core.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace FSharp.Json

open FSharp.Json
open FSharp.Json.Internalized.FSharp.Data

module internal Core =
open System
open System.Globalization
Expand Down Expand Up @@ -249,6 +252,7 @@ module internal Core =
let jkey = (jsonUnion.CaseKeyField, JsonValue.String theCase)
let jvalue = (jsonUnion.CaseValueField, jvalue)
JsonValue.Record [| jkey; jvalue |]
| UnionMode.AsValue -> jvalue
| UnionMode.CaseKeyDiscriminatorField ->
match jvalue with
| JsonValue.Record jrecord ->
Expand Down Expand Up @@ -515,6 +519,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 ->
Expand Down
2 changes: 2 additions & 0 deletions FSharp.Json/InterfaceTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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 () =
Expand Down