Skip to content

Commit 7ce136a

Browse files
committed
feat: add WithOverrideMembers for record fields
1 parent 01b26f8 commit 7ce136a

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

src/FSharp.SystemTextJson/Options.fs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ type internal JsonFSharpOptionsRecord =
185185
MapFormat: MapFormat
186186
Types: JsonFSharpTypes
187187
AllowOverride: bool
188+
OverrideMembers: IDictionary<string, seq<Attribute>>
188189
Overrides: JsonFSharpOptions -> IDictionary<Type, JsonFSharpOptions> }
189190

190191
and JsonFSharpOptions internal (options: JsonFSharpOptionsRecord) =
@@ -224,6 +225,7 @@ and JsonFSharpOptions internal (options: JsonFSharpOptionsRecord) =
224225
MapFormat = MapFormat.ObjectOrArrayOfPairs
225226
Types = types
226227
AllowOverride = allowOverride
228+
OverrideMembers = Map.empty
227229
Overrides = emptyOverrides }
228230
)
229231

@@ -340,6 +342,9 @@ and JsonFSharpOptions internal (options: JsonFSharpOptionsRecord) =
340342
member _.WithOverrides(overrides) =
341343
JsonFSharpOptions({ options with Overrides = fun _ -> overrides })
342344

345+
member _.WithOverrideMembers(overrides) =
346+
JsonFSharpOptions({ options with OverrideMembers = overrides })
347+
343348
member private this.WithUnionEncodingFlag(flag, set) =
344349
if set then
345350
this.WithUnionEncoding(options.UnionEncoding ||| flag)

src/FSharp.SystemTextJson/Record.fs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ open FSharp.Reflection
88
open System.Text.Json.Serialization.Helpers
99

1010
type private RecordField
11+
private
1112
(
1213
fsOptions: JsonFSharpOptionsRecord,
1314
options: JsonSerializerOptions,
@@ -37,7 +38,18 @@ type private RecordField
3738

3839
new(fsOptions, options: JsonSerializerOptions, i, p: PropertyInfo, fieldOrderIndices) =
3940
let names =
40-
match getJsonNames "field" (fun ty -> p.GetCustomAttributes(ty, true)) with
41+
match
42+
getJsonNames
43+
"field"
44+
(fun ty ->
45+
match fsOptions.OverrideMembers.TryGetValue(p.Name) with
46+
| true, attrs ->
47+
[| for attr in attrs do
48+
if attr.GetType().IsAssignableFrom(ty) then
49+
box attr |]
50+
| false, _ -> p.GetCustomAttributes(ty, true)
51+
)
52+
with
4153
| ValueSome names -> names |> Array.map (fun n -> n.AsString())
4254
| ValueNone -> [| convertName options.PropertyNamingPolicy p.Name |]
4355
RecordField(fsOptions, options, i, p, fieldOrderIndices, names)

tests/FSharp.SystemTextJson.Tests/Test.Record.fs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,26 @@ module NonStruct =
497497
JsonSerializer.Serialize({ incX = 1; incY = "a" }, dontIncludeRecordPropertiesOptions)
498498
Assert.Equal("""{"incX":1,"incY":"a","incZ":42}""", actual)
499499

500+
type OverrideMembersRecord = { x: int; y: string }
501+
502+
let overrideMembersOptions =
503+
JsonFSharpOptions()
504+
.WithOverrides(fun o ->
505+
dict [ typeof<OverrideMembersRecord>, o.WithOverrideMembers(dict [ "x", [ JsonNameAttribute("z") ] ]) ]
506+
)
507+
.ToJsonSerializerOptions()
508+
509+
[<Fact>]
510+
let ``serialize with OverrideMembers`` () =
511+
let actual = JsonSerializer.Serialize({ x = 1; y = "b" }, overrideMembersOptions)
512+
Assert.Equal("""{"z":1,"y":"b"}""", actual)
513+
514+
[<Fact>]
515+
let ``deserialize with OverrideMembers`` () =
516+
let actual =
517+
JsonSerializer.Deserialize<OverrideMembersRecord>("""{"z":1,"y":"b"}""", overrideMembersOptions)
518+
Assert.Equal({ x = 1; y = "b" }, actual)
519+
500520
module Struct =
501521

502522
[<Struct; JsonFSharpConverter>]
@@ -943,3 +963,24 @@ module Struct =
943963
let actual =
944964
JsonSerializer.Serialize({ incX = 1; incY = "a" }, dontIncludeRecordPropertiesOptions)
945965
Assert.Equal("""{"incX":1,"incY":"a","incZ":42}""", actual)
966+
967+
[<Struct>]
968+
type OverrideMembersRecord = { x: int; y: string }
969+
970+
let overrideMembersOptions =
971+
JsonFSharpOptions()
972+
.WithOverrides(fun o ->
973+
dict [ typeof<OverrideMembersRecord>, o.WithOverrideMembers(dict [ "x", [ JsonNameAttribute("z") ] ]) ]
974+
)
975+
.ToJsonSerializerOptions()
976+
977+
[<Fact>]
978+
let ``serialize with OverrideMembers`` () =
979+
let actual = JsonSerializer.Serialize({ x = 1; y = "b" }, overrideMembersOptions)
980+
Assert.Equal("""{"z":1,"y":"b"}""", actual)
981+
982+
[<Fact>]
983+
let ``deserialize with OverrideMembers`` () =
984+
let actual =
985+
JsonSerializer.Deserialize<OverrideMembersRecord>("""{"z":1,"y":"b"}""", overrideMembersOptions)
986+
Assert.Equal({ x = 1; y = "b" }, actual)

0 commit comments

Comments
 (0)