Skip to content
Closed
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 @@
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 Expand Up @@ -195,4 +220,4 @@
let json = """{"Main":null}"""
let expected = Main None
let actual = Json.deserialize<UnionWithOption> json
Assert.AreEqual(expected, actual)

Check warning on line 223 in FSharp.Json.Tests/Union.fs

View workflow job for this annotation

GitHub Actions / build

Main module of program is empty: nothing will happen when it is run

Check warning on line 223 in FSharp.Json.Tests/Union.fs

View workflow job for this annotation

GitHub Actions / build

Main module of program is empty: nothing will happen when it is run
11 changes: 8 additions & 3 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 @@ -78,7 +81,7 @@
let enumMode = getEnumMode config jsonField
match enumMode with
| EnumMode.Value ->
match baseT with

Check warning on line 84 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression.

Check warning on line 84 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression.
| t when t = typeof<int> ->
let enumValue = decimal (value :?> int)
JsonValue.Number enumValue
Expand Down Expand Up @@ -248,9 +251,10 @@
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 ->
Expand Down Expand Up @@ -299,7 +303,7 @@
let enumMode = getEnumMode config jsonField
match enumMode with
| EnumMode.Value ->
match baseT with

Check warning on line 306 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression.

Check warning on line 306 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression.
| baseT when baseT = typeof<int> ->
let enumValue = JsonValueHelpers.getInt path jValue
Enum.ToObject(t, enumValue)
Expand Down Expand Up @@ -519,10 +523,11 @@
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 ->
match jsonUnion.Mode with

Check warning on line 530 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression. For example, the value 'UnionMode.AsValue' may indicate a case not covered by the pattern(s).

Check warning on line 530 in FSharp.Json/Core.fs

View workflow job for this annotation

GitHub Actions / build

Incomplete pattern matches on this expression. For example, the value 'UnionMode.AsValue' may indicate a case not covered by the pattern(s).
| UnionMode.CaseKeyDiscriminatorField ->
let caseKeyFieldName, caseKeyFieldValue = mustFindField path jsonUnion.CaseKeyField fields
let caseNamePath = caseKeyFieldName |> JsonPathItem.Field |> path.createNew
Expand Down Expand Up @@ -550,4 +555,4 @@
| 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}."


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
Loading