diff --git a/src/FSharp.SystemTextJson/Union.fs b/src/FSharp.SystemTextJson/Union.fs index 3282926..f8f03ab 100644 --- a/src/FSharp.SystemTextJson/Union.fs +++ b/src/FSharp.SystemTextJson/Union.fs @@ -702,18 +702,32 @@ type JsonUnwrapValueOptionConverter<'T>() = | ValueNone -> writer.WriteNullValue() | ValueSome x -> JsonSerializer.Serialize<'T>(writer, x, options) -type JsonUnwrappedUnionConverter<'T, 'FieldT>(case: UnionCaseInfo) = +type JsonUnwrappedUnionConverter<'T, 'FieldT>(case: UnionCaseInfo, options: JsonSerializerOptions) = inherit JsonConverter<'T>() let ctor = FSharpValue.PreComputeUnionConstructor(case, true) let getter = FSharpValue.PreComputeUnionReader(case, true) + let innerConverter = + match options.GetConverter(typeof<'FieldT>) with + | :? JsonConverter<'FieldT> as c -> c + | _ -> null override _.Read(reader, _typeToConvert, options) = ctor [| box (JsonSerializer.Deserialize<'FieldT>(&reader, options)) |] :?> 'T + override _.ReadAsPropertyName(reader, typeToConvert, options) = + match innerConverter with + | null -> base.ReadAsPropertyName(&reader, typeToConvert, options) + | innerConverter -> ctor [| innerConverter.ReadAsPropertyName(&reader, typeof<'FieldT>, options) |] :?> 'T + override _.Write(writer, value, options) = JsonSerializer.Serialize<'FieldT>(writer, (getter value)[0] :?> 'FieldT, options) + override _.WriteAsPropertyName(writer, value, options) = + match innerConverter with + | null -> base.WriteAsPropertyName(writer, value, options) + | innerConverter -> innerConverter.WriteAsPropertyName(writer, (getter value)[0] :?> 'FieldT, options) + type JsonUnionConverter(fsOptions: JsonFSharpOptions) = inherit JsonConverterFactory() @@ -769,8 +783,8 @@ type JsonUnionConverter(fsOptions: JsonFSharpOptions) = let case = cases[0] jsonUnwrappedUnionConverterTy .MakeGenericType([| typeToConvert; unwrappedSingleCaseField.PropertyType |]) - .GetConstructor([| caseTy |]) - .Invoke([| case |]) + .GetConstructor([| caseTy; typeof |]) + .Invoke([| case; options |]) :?> JsonConverter | false, cases, _ -> jsonUnionConverterTy diff --git a/tests/FSharp.SystemTextJson.Tests/Test.Collection.fs b/tests/FSharp.SystemTextJson.Tests/Test.Collection.fs index 77dd6b4..f10edfc 100644 --- a/tests/FSharp.SystemTextJson.Tests/Test.Collection.fs +++ b/tests/FSharp.SystemTextJson.Tests/Test.Collection.fs @@ -98,6 +98,22 @@ let ``serialize newtype-string-keyed map`` (m: Map, int>) = let actual = JsonSerializer.Serialize(m, options) Assert.Equal(expected, actual) +[] +let ``deserialize newtype-string-keyed dictionary`` (d': Dictionary, int>) = + let d = Dictionary() + for KeyValue(NonNull k, v) in d' do d[UserId k] <- v + let ser = "{" + String.concat "," (Seq.map serKV1_1 d) + "}" + let actual = JsonSerializer.Deserialize>(ser, options) + Assert.Equal>(d, actual) + +[] +let ``serialize newtype-string-keyed dictionary`` (d': Dictionary, int>) = + let d = Dictionary() + for KeyValue(NonNull k, v) in d' do d[UserId k] <- v + let expected = "{" + String.concat "," (Seq.map serKV1_1 d) + "}" + let actual = JsonSerializer.Serialize(d, options) + Assert.Equal(expected, actual) + [] type SUserId = SUserId of string @@ -118,6 +134,22 @@ let ``serialize struct-newtype-string-keyed map`` (m: Map, int>) let actual = JsonSerializer.Serialize(m, options) Assert.Equal(expected, actual) +[] +let ``deserialize struct-newtype-string-keyed dictionary`` (d': Dictionary, int>) = + let d = Dictionary() + for KeyValue(NonNull k, v) in d' do d[SUserId k] <- v + let ser = "{" + String.concat "," (Seq.map serKV1_2 d) + "}" + let actual = JsonSerializer.Deserialize>(ser, options) + Assert.Equal>(d, actual) + +[] +let ``serialize struct-newtype-string-keyed dictionary`` (d': Dictionary, int>) = + let d = Dictionary() + for KeyValue(NonNull k, v) in d' do d[SUserId k] <- v + let expected = "{" + String.concat "," (Seq.map serKV1_2 d) + "}" + let actual = JsonSerializer.Serialize(d, options) + Assert.Equal(expected, actual) + let keyPolicyOptions = JsonFSharpOptions() .ToJsonSerializerOptions(DictionaryKeyPolicy = JsonNamingPolicy.CamelCase)