Skip to content

Commit

Permalink
[#108] Add unionFieldNamingPolicy
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarmil committed Jun 8, 2022
1 parent 0ff1eb0 commit ab70a9a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 16 deletions.
6 changes: 4 additions & 2 deletions src/FSharp.SystemTextJson/All.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type JsonFSharpConverter
unionFieldsName: JsonUnionFieldsName,
[<Optional; DefaultParameterValue(Default.UnionTagNamingPolicy)>]
unionTagNamingPolicy: JsonNamingPolicy,
[<Optional; DefaultParameterValue(Default.UnionTagNamingPolicy)>]
unionFieldNamingPolicy: JsonNamingPolicy,
[<Optional; DefaultParameterValue(Default.UnionTagCaseInsensitive)>]
unionTagCaseInsensitive: bool,
[<Optional; DefaultParameterValue(Default.AllowNullFields)>]
Expand All @@ -54,7 +56,7 @@ type JsonFSharpConverter
[<Optional>]
overrides: IDictionary<Type, JsonFSharpOptions>
) =
JsonFSharpConverter(JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, unionTagNamingPolicy, unionTagCaseInsensitive, allowNullFields, allowOverride), overrides)
JsonFSharpConverter(JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, unionTagNamingPolicy, unionFieldNamingPolicy, unionTagCaseInsensitive, allowNullFields, allowOverride), overrides)

[<AttributeUsage(AttributeTargets.Class ||| AttributeTargets.Struct)>]
type JsonFSharpConverterAttribute
Expand All @@ -74,7 +76,7 @@ type JsonFSharpConverterAttribute

let options = JsonSerializerOptions()

let fsOptions = JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, Default.UnionTagNamingPolicy, unionTagCaseInsensitive, allowNullFields, false)
let fsOptions = JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, Default.UnionTagNamingPolicy, Default.UnionFieldNamingPolicy, unionTagCaseInsensitive, allowNullFields, false)

override _.CreateConverter(typeToConvert) =
JsonFSharpConverter.CreateConverter(typeToConvert, options, fsOptions, null)
Expand Down
8 changes: 7 additions & 1 deletion src/FSharp.SystemTextJson/Options.fs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ module internal Default =
let [<Literal>] UnionFieldsName = "Fields"

let [<Literal>] UnionTagNamingPolicy = null : JsonNamingPolicy

let [<Literal>] UnionFieldNamingPolicy = null : JsonNamingPolicy

let [<Literal>] UnionTagCaseInsensitive = false

Expand All @@ -119,6 +121,8 @@ type JsonFSharpOptions
unionFieldsName: JsonUnionFieldsName,
[<Optional; DefaultParameterValue(Default.UnionTagNamingPolicy)>]
unionTagNamingPolicy: JsonNamingPolicy,
[<Optional; DefaultParameterValue(Default.UnionTagNamingPolicy)>]
unionFieldNamingPolicy: JsonNamingPolicy,
[<Optional; DefaultParameterValue(Default.UnionTagCaseInsensitive)>]
unionTagCaseInsensitive: bool,
[<Optional; DefaultParameterValue(Default.AllowNullFields)>]
Expand All @@ -135,14 +139,16 @@ type JsonFSharpOptions

member this.UnionTagNamingPolicy = unionTagNamingPolicy

member this.UnionFieldNamingPolicy = unionFieldNamingPolicy

member this.UnionTagCaseInsensitive = unionTagCaseInsensitive

member this.AllowNullFields = allowNullFields

member this.AllowOverride = allowOverride

member this.WithUnionEncoding(unionEncoding) =
JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, unionTagNamingPolicy, unionTagCaseInsensitive, allowNullFields, allowOverride)
JsonFSharpOptions(unionEncoding, unionTagName, unionFieldsName, unionTagNamingPolicy, unionFieldNamingPolicy, unionTagCaseInsensitive, allowNullFields, allowOverride)

type IJsonFSharpConverterAttribute =
abstract Options: JsonFSharpOptions
6 changes: 5 additions & 1 deletion src/FSharp.SystemTextJson/Union.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ type JsonUnionConverter<'T>
{
Type = p.PropertyType
Name =
match options.PropertyNamingPolicy with
let policy =
match fsOptions.UnionFieldNamingPolicy with
| null -> options.PropertyNamingPolicy
| policy -> policy
match policy with
| null -> name
| policy -> policy.ConvertName name
MustBeNonNull = not (isNullableFieldType fsOptions p.PropertyType)
Expand Down
66 changes: 54 additions & 12 deletions tests/FSharp.SystemTextJson.Tests/Test.Union.fs
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,8 @@ module NonStruct =
type NamedAfterTypes =
| NTA of int
| NTB of int * string
| NTC of x: int
| NTD of x: int * y: string
| NTC of X: int
| NTD of X: int * Y: string
| NTE of string * string

let namedAfterTypesOptions = JsonSerializerOptions()
Expand All @@ -651,18 +651,39 @@ module NonStruct =
let ``serialize UnionFieldNamesFromTypes`` () =
Assert.Equal("""{"Case":"NTA","Int32":123}""", JsonSerializer.Serialize(NTA 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTB","Int32":123,"String":"test"}""", JsonSerializer.Serialize(NTB(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTC","x":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTD","x":123,"y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTC","X":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTD","X":123,"Y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTE","String1":"123","String2":"test"}""", JsonSerializer.Serialize(NTE("123", "test"), namedAfterTypesOptions))

[<Fact>]
let ``deserialize UnionFieldNamesFromTypes`` () =
Assert.Equal(NTA 123, JsonSerializer.Deserialize("""{"Case":"NTA","Int32":123}""", namedAfterTypesOptions))
Assert.Equal(NTB(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTB","Int32":123,"String":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","x":123}""", namedAfterTypesOptions))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","x":123,"y":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","X":123}""", namedAfterTypesOptions))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","X":123,"Y":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTE("123", "test"), JsonSerializer.Deserialize("""{"Case":"NTE","String1":"123","String2":"test"}""", namedAfterTypesOptions))

let namedAfterTypesOptionsWithNamingPolicy = JsonSerializerOptions()
namedAfterTypesOptionsWithNamingPolicy.Converters.Add(
JsonFSharpConverter(JsonUnionEncoding.InternalTag ||| JsonUnionEncoding.NamedFields ||| JsonUnionEncoding.UnionFieldNamesFromTypes,
unionFieldNamingPolicy = JsonNamingPolicy.CamelCase))

[<Fact>]
let ``serialize UnionFieldNamesFromTypes with unionFieldNamingPolicy`` () =
Assert.Equal("""{"Case":"NTA","int32":123}""", JsonSerializer.Serialize(NTA 123, namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTB","int32":123,"string":"test"}""", JsonSerializer.Serialize(NTB(123, "test"), namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTC","x":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTD","x":123,"y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTE","string1":"123","string2":"test"}""", JsonSerializer.Serialize(NTE("123", "test"), namedAfterTypesOptionsWithNamingPolicy))

[<Fact>]
let ``deserialize UnionFieldNamesFromTypes with unionFieldNamingPolicy`` () =
Assert.Equal(NTA 123, JsonSerializer.Deserialize("""{"Case":"NTA","int32":123}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTB(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTB","int32":123,"string":"test"}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","x":123}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","x":123,"y":"test"}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTE("123", "test"), JsonSerializer.Deserialize("""{"Case":"NTE","string1":"123","string2":"test"}""", namedAfterTypesOptionsWithNamingPolicy))

module Struct =

[<Struct; JsonFSharpConverter>]
Expand Down Expand Up @@ -1280,9 +1301,9 @@ module Struct =
[<Struct>]
type NamedAfterTypesB = NTB of int * string
[<Struct>]
type NamedAfterTypesC = NTC of x: int
type NamedAfterTypesC = NTC of X: int
[<Struct>]
type NamedAfterTypesD = NTD of x: int * y: string
type NamedAfterTypesD = NTD of X: int * Y: string
[<Struct>]
type NamedAfterTypesE = NTE of string * string

Expand All @@ -1293,14 +1314,35 @@ module Struct =
let ``serialize UnionFieldNamesFromTypes`` () =
Assert.Equal("""{"Case":"NTA","Int32":123}""", JsonSerializer.Serialize(NTA 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTB","Int32":123,"String":"test"}""", JsonSerializer.Serialize(NTB(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTC","x":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTD","x":123,"y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTC","X":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTD","X":123,"Y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptions))
Assert.Equal("""{"Case":"NTE","String1":"123","String2":"test"}""", JsonSerializer.Serialize(NTE("123", "test"), namedAfterTypesOptions))

[<Fact>]
let ``deserialize UnionFieldNamesFromTypes`` () =
Assert.Equal(NTA 123, JsonSerializer.Deserialize("""{"Case":"NTA","Int32":123}""", namedAfterTypesOptions))
Assert.Equal(NTB(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTB","Int32":123,"String":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","x":123}""", namedAfterTypesOptions))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","x":123,"y":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","X":123}""", namedAfterTypesOptions))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","X":123,"Y":"test"}""", namedAfterTypesOptions))
Assert.Equal(NTE("123", "test"), JsonSerializer.Deserialize("""{"Case":"NTE","String1":"123","String2":"test"}""", namedAfterTypesOptions))

let namedAfterTypesOptionsWithNamingPolicy = JsonSerializerOptions()
namedAfterTypesOptionsWithNamingPolicy.Converters.Add(
JsonFSharpConverter(JsonUnionEncoding.InternalTag ||| JsonUnionEncoding.NamedFields ||| JsonUnionEncoding.UnionFieldNamesFromTypes,
unionFieldNamingPolicy = JsonNamingPolicy.CamelCase))

[<Fact>]
let ``serialize UnionFieldNamesFromTypes with unionFieldNamingPolicy`` () =
Assert.Equal("""{"Case":"NTA","int32":123}""", JsonSerializer.Serialize(NTA 123, namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTB","int32":123,"string":"test"}""", JsonSerializer.Serialize(NTB(123, "test"), namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTC","x":123}""", JsonSerializer.Serialize(NTC 123, namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTD","x":123,"y":"test"}""", JsonSerializer.Serialize(NTD(123, "test"), namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal("""{"Case":"NTE","string1":"123","string2":"test"}""", JsonSerializer.Serialize(NTE("123", "test"), namedAfterTypesOptionsWithNamingPolicy))

[<Fact>]
let ``deserialize UnionFieldNamesFromTypes with unionFieldNamingPolicy`` () =
Assert.Equal(NTA 123, JsonSerializer.Deserialize("""{"Case":"NTA","int32":123}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTB(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTB","int32":123,"string":"test"}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTC 123, JsonSerializer.Deserialize("""{"Case":"NTC","x":123}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTD(123, "test"), JsonSerializer.Deserialize("""{"Case":"NTD","x":123,"y":"test"}""", namedAfterTypesOptionsWithNamingPolicy))
Assert.Equal(NTE("123", "test"), JsonSerializer.Deserialize("""{"Case":"NTE","string1":"123","string2":"test"}""", namedAfterTypesOptionsWithNamingPolicy))

0 comments on commit ab70a9a

Please sign in to comment.