diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 6691df19ae1939..bcd039e90cbfa7 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -111,6 +111,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs index 62835f45b94061..3ca47a7ebba490 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs @@ -74,12 +74,28 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, return true; } + public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); + return null!; + } + internal override object ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); return null!; } + public override void WriteAsPropertyName(Utf8JsonWriter writer, object? value, JsonSerializerOptions options) + { + if (value is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(value)); + } + + WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); + } + internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, object? value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { // This converter does not handle nulls. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/BooleanConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/BooleanConverter.cs index 1345659c0f64fc..c12f9447bb0053 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/BooleanConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/BooleanConverter.cs @@ -6,7 +6,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class BooleanConverter : JsonConverter + internal sealed class BooleanConverter : JsonPrimitiveConverter { public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -20,6 +20,7 @@ public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOpti internal override bool ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); ReadOnlySpan propertyName = reader.GetSpan(); if (!(Utf8Parser.TryParse(propertyName, out bool value, out int bytesConsumed) && propertyName.Length == bytesConsumed)) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ByteConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ByteConverter.cs index c927119345d937..9df14e2060976c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ByteConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ByteConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class ByteConverter : JsonConverter + internal sealed class ByteConverter : JsonPrimitiveConverter { public ByteConverter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, byte value, JsonSerializerOpti internal override byte ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetByteWithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs index 5b829b49084986..b3caa32d186bca 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs @@ -6,7 +6,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class CharConverter : JsonConverter + internal sealed class CharConverter : JsonPrimitiveConverter { private const int MaxEscapedCharacterLength = JsonConstants.MaxExpansionFactorWhileEscaping; @@ -40,7 +40,10 @@ public override void Write(Utf8JsonWriter writer, char value, JsonSerializerOpti } internal override char ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => Read(ref reader, typeToConvert, options); + { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); + return Read(ref reader, typeToConvert, options); + } internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, char value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs index 0aaec4759d0b75..16b4e5e82ec6d1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs @@ -7,7 +7,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class DateOnlyConverter : JsonConverter + internal sealed class DateOnlyConverter : JsonPrimitiveConverter { public const int FormatLength = 10; // YYYY-MM-DD public const int MaxEscapedFormatLength = FormatLength * JsonConstants.MaxExpansionFactorWhileEscaping; @@ -24,10 +24,11 @@ public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, Jso internal override DateOnly ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return ReadCore(ref reader); } - private DateOnly ReadCore(ref Utf8JsonReader reader) + private static DateOnly ReadCore(ref Utf8JsonReader reader) { if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, FormatLength, MaxEscapedFormatLength)) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeConverter.cs index 85cb86b15e0cd8..204d39551cea29 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class DateTimeConverter : JsonConverter + internal sealed class DateTimeConverter : JsonPrimitiveConverter { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -17,6 +19,7 @@ public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializer internal override DateTime ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetDateTimeNoValidation(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeOffsetConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeOffsetConverter.cs index 82a6581be80e49..6cfeaf4c38edcd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeOffsetConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateTimeOffsetConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class DateTimeOffsetConverter : JsonConverter + internal sealed class DateTimeOffsetConverter : JsonPrimitiveConverter { public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -17,6 +19,7 @@ public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSeri internal override DateTimeOffset ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetDateTimeOffsetNoValidation(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DecimalConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DecimalConverter.cs index 52c94458141bee..7b3ff9fade01d6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DecimalConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DecimalConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class DecimalConverter : JsonConverter + internal sealed class DecimalConverter : JsonPrimitiveConverter { public DecimalConverter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerO internal override decimal ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetDecimalWithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DoubleConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DoubleConverter.cs index 34499fb350042a..0c6a6c4e26cc65 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DoubleConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DoubleConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class DoubleConverter : JsonConverter + internal sealed class DoubleConverter : JsonPrimitiveConverter { public DoubleConverter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOp internal override double ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetDoubleWithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index d9de4d1f0fbe4a..7b002db36f83bc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -10,7 +10,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class EnumConverter : JsonConverter + internal sealed class EnumConverter : JsonPrimitiveConverter where T : struct, Enum { private static readonly TypeCode s_enumTypeCode = Type.GetTypeCode(typeof(T)); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/GuidConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/GuidConverter.cs index b0c358b67aa762..c808bc6d730ba3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/GuidConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/GuidConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class GuidConverter : JsonConverter + internal sealed class GuidConverter : JsonPrimitiveConverter { public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -17,6 +19,7 @@ public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOpti internal override Guid ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetGuidNoValidation(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int16Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int16Converter.cs index 2ada98b75c0841..73da887f71c922 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int16Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int16Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class Int16Converter : JsonConverter + internal sealed class Int16Converter : JsonPrimitiveConverter { public Int16Converter() { @@ -23,6 +25,7 @@ public override void Write(Utf8JsonWriter writer, short value, JsonSerializerOpt internal override short ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetInt16WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int32Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int32Converter.cs index 49ba9d15f3cc37..a243b0d65f26e5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int32Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int32Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class Int32Converter : JsonConverter + internal sealed class Int32Converter : JsonPrimitiveConverter { public Int32Converter() { @@ -23,6 +25,7 @@ public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptio internal override int ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetInt32WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int64Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int64Converter.cs index 038deb5524705d..7987daf7c6916c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int64Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/Int64Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class Int64Converter : JsonConverter + internal sealed class Int64Converter : JsonPrimitiveConverter { public Int64Converter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOpti internal override long ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetInt64WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/JsonPrimitiveConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/JsonPrimitiveConverter.cs new file mode 100644 index 00000000000000..8da98cb141fef0 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/JsonPrimitiveConverter.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json.Serialization.Converters +{ + /// + /// Inherited by built-in converters serializing types as JSON primitives that support property name serialization. + /// + internal abstract class JsonPrimitiveConverter : JsonConverter + { + public sealed override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + if (value is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(value)); + } + + WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); + } + + public sealed override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.PropertyName) + { + ThrowHelper.ThrowInvalidOperationException_ExpectedPropertyName(reader.TokenType); + } + + return ReadAsPropertyNameCore(ref reader, typeToConvert, options); + } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SByteConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SByteConverter.cs index 198ec2d9e6e9bd..f302fd6a04565a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SByteConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SByteConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class SByteConverter : JsonConverter + internal sealed class SByteConverter : JsonPrimitiveConverter { public SByteConverter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, sbyte value, JsonSerializerOpt internal override sbyte ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetSByteWithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SingleConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SingleConverter.cs index 5ce4cf603016a7..4c6b2c5a80674e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SingleConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/SingleConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class SingleConverter : JsonConverter + internal sealed class SingleConverter : JsonPrimitiveConverter { public SingleConverter() @@ -23,6 +25,7 @@ public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOpt internal override float ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetSingleWithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/StringConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/StringConverter.cs index a2ef84679e4267..2984a0a5bc9f6a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/StringConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/StringConverter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class StringConverter : JsonConverter + internal sealed class StringConverter : JsonPrimitiveConverter { public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -25,6 +27,7 @@ public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerO internal override string ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetString()!; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeOnlyConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeOnlyConverter.cs index 73cb0c6012720c..29ee02876ac624 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeOnlyConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeOnlyConverter.cs @@ -6,7 +6,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class TimeOnlyConverter : JsonConverter + internal sealed class TimeOnlyConverter : JsonPrimitiveConverter { private const int MinimumTimeOnlyFormatLength = 8; // hh:mm:ss private const int MaximumTimeOnlyFormatLength = 16; // hh:mm:ss.fffffff @@ -19,6 +19,19 @@ public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, Jso ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType); } + return ReadCore(ref reader); + } + + internal override TimeOnly ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); + return ReadCore(ref reader); + } + + private static TimeOnly ReadCore(ref Utf8JsonReader reader) + { + Debug.Assert(reader.TokenType is JsonTokenType.String or JsonTokenType.PropertyName); + if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, MinimumTimeOnlyFormatLength, MaximumEscapedTimeOnlyFormatLength)) { ThrowHelper.ThrowFormatException(DataType.TimeOnly); @@ -70,5 +83,15 @@ public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializer writer.WriteStringValue(output.Slice(0, bytesWritten)); } + + internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) + { + Span output = stackalloc byte[MaximumTimeOnlyFormatLength]; + + bool result = Utf8Formatter.TryFormat(value.ToTimeSpan(), output, out int bytesWritten, 'c'); + Debug.Assert(result); + + writer.WritePropertyName(output.Slice(0, bytesWritten)); + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs index c956080c6885b9..245f5ea4afc1f2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs @@ -1,13 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; using System.Buffers.Text; using System.Diagnostics; namespace System.Text.Json.Serialization.Converters { - internal sealed class TimeSpanConverter : JsonConverter + internal sealed class TimeSpanConverter : JsonPrimitiveConverter { private const int MinimumTimeSpanFormatLength = 8; // hh:mm:ss private const int MaximumTimeSpanFormatLength = 26; // -dddddddd.hh:mm:ss.fffffff @@ -20,6 +19,19 @@ public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, Jso ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType); } + return ReadCore(ref reader); + } + + internal override TimeSpan ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); + return ReadCore(ref reader); + } + + private static TimeSpan ReadCore(ref Utf8JsonReader reader) + { + Debug.Assert(reader.TokenType is JsonTokenType.String or JsonTokenType.PropertyName); + if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, MinimumTimeSpanFormatLength, MaximumEscapedTimeSpanFormatLength)) { ThrowHelper.ThrowFormatException(DataType.TimeSpan); @@ -69,5 +81,15 @@ public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializer writer.WriteStringValue(output.Slice(0, bytesWritten)); } + + internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) + { + Span output = stackalloc byte[MaximumTimeSpanFormatLength]; + + bool result = Utf8Formatter.TryFormat(value, output, out int bytesWritten, 'c'); + Debug.Assert(result); + + writer.WritePropertyName(output.Slice(0, bytesWritten)); + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt16Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt16Converter.cs index 0ac6a644faf760..16c717cb7d440d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt16Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt16Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class UInt16Converter : JsonConverter + internal sealed class UInt16Converter : JsonPrimitiveConverter { public UInt16Converter() { @@ -23,6 +25,7 @@ public override void Write(Utf8JsonWriter writer, ushort value, JsonSerializerOp internal override ushort ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetUInt16WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt32Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt32Converter.cs index c0d2a754ee062c..9a8dccb9b80cf6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt32Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt32Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class UInt32Converter : JsonConverter + internal sealed class UInt32Converter : JsonPrimitiveConverter { public UInt32Converter() { @@ -23,6 +25,7 @@ public override void Write(Utf8JsonWriter writer, uint value, JsonSerializerOpti internal override uint ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetUInt32WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt64Converter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt64Converter.cs index f63d9175abb390..7b3290a4787589 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt64Converter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UInt64Converter.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Text.Json.Serialization.Converters { - internal sealed class UInt64Converter : JsonConverter + internal sealed class UInt64Converter : JsonPrimitiveConverter { public UInt64Converter() { @@ -22,6 +24,7 @@ public override void Write(Utf8JsonWriter writer, ulong value, JsonSerializerOpt internal override ulong ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); return reader.GetUInt64WithQuotes(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UriConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UriConverter.cs index b256436b0c5c09..e50a6521abda30 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UriConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UriConverter.cs @@ -1,9 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; +using System.Runtime.CompilerServices; + namespace System.Text.Json.Serialization.Converters { - internal sealed class UriConverter : JsonConverter + internal sealed class UriConverter : JsonPrimitiveConverter { public override Uri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -21,5 +24,16 @@ public override void Write(Utf8JsonWriter writer, Uri value, JsonSerializerOptio { writer.WriteStringValue(value.OriginalString); } + + internal override Uri ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Debug.Assert(reader.TokenType is JsonTokenType.PropertyName); + return Read(ref reader, typeToConvert, options); + } + + internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) + { + writer.WritePropertyName(value.OriginalString); + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs index 4343672f429117..fa4d0a07dbb9e7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs @@ -1,13 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; -using System.Buffers.Text; using System.Diagnostics; namespace System.Text.Json.Serialization.Converters { - internal sealed class VersionConverter : JsonConverter + internal sealed class VersionConverter : JsonPrimitiveConverter { #if NETCOREAPP private const int MinimumVersionLength = 3; // 0.0 @@ -24,6 +22,13 @@ public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, Json ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType); } + return ReadCore(ref reader); + } + + private static Version ReadCore(ref Utf8JsonReader reader) + { + Debug.Assert(reader.TokenType is JsonTokenType.PropertyName or JsonTokenType.String); + #if NETCOREAPP if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, MinimumVersionLength, MaximumEscapedVersionLength)) { @@ -75,6 +80,23 @@ public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerO writer.WriteStringValue(span.Slice(0, charsWritten)); #else writer.WriteStringValue(value.ToString()); +#endif + } + + internal override Version ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return ReadCore(ref reader); + } + + internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Version value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) + { +#if NETCOREAPP + Span span = stackalloc char[MaximumVersionLength]; + bool formattedSuccessfully = value.TryFormat(span, out int charsWritten); + Debug.Assert(formattedSuccessfully && charsWritten >= MinimumVersionLength); + writer.WritePropertyName(span.Slice(0, charsWritten)); +#else + writer.WritePropertyName(value.ToString()); #endif } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index c69ba39daf4dd8..dce96390de41c5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -583,19 +583,14 @@ public abstract void Write( /// Method should be overridden in custom converters of types used in deserialized dictionary keys. public virtual T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (!IsInternalConverter && - options.SerializerContext is null && // For consistency do not return any default converters for - // options instances linked to a JsonSerializerContext, - // even if the default converters might have been rooted. - DefaultJsonTypeInfoResolver.TryGetDefaultSimpleConverter(TypeToConvert, out JsonConverter? defaultConverter)) + // .NET 5 backward compatibility: hardcode the default converter for primitive key serialization. + JsonConverter? fallbackConverter = GetFallbackConverterForPropertyNameSerialization(options); + if (fallbackConverter is null) { - // .NET 5 backward compatibility: hardcode the default converter for primitive key serialization. - Debug.Assert(defaultConverter.IsInternalConverter && defaultConverter is JsonConverter); - return ((JsonConverter)defaultConverter).ReadAsPropertyNameCore(ref reader, TypeToConvert, options); + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); } - ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); - return default; + return fallbackConverter.ReadAsPropertyNameCore(ref reader, typeToConvert, options); } internal virtual T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -621,19 +616,14 @@ internal virtual T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeTo /// Method should be overridden in custom converters of types used in serialized dictionary keys. public virtual void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - if (!IsInternalConverter && - options.SerializerContext is null && // For consistency do not return any default converters for - // options instances linked to a JsonSerializerContext, - // even if the default converters might have been rooted. - DefaultJsonTypeInfoResolver.TryGetDefaultSimpleConverter(TypeToConvert, out JsonConverter? defaultConverter)) + // .NET 5 backward compatibility: hardcode the default converter for primitive key serialization. + JsonConverter? fallbackConverter = GetFallbackConverterForPropertyNameSerialization(options); + if (fallbackConverter is null) { - // .NET 5 backward compatibility: hardcode the default converter for primitive key serialization. - Debug.Assert(defaultConverter.IsInternalConverter && defaultConverter is JsonConverter); - ((JsonConverter)defaultConverter).WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); - return; + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); } - ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); + fallbackConverter.WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); } internal virtual void WriteAsPropertyNameCore(Utf8JsonWriter writer, T value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) @@ -658,6 +648,29 @@ internal virtual void WriteAsPropertyNameCore(Utf8JsonWriter writer, T value, Js internal sealed override void WriteAsPropertyNameCoreAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) => WriteAsPropertyNameCore(writer, (T)value, options, isWritingExtensionDataProperty); + // .NET 5 backward compatibility: hardcode the default converter for primitive key serialization. + private JsonConverter? GetFallbackConverterForPropertyNameSerialization(JsonSerializerOptions options) + { + JsonConverter? result = null; + + // For consistency do not return any default converters for options instances linked to a + // JsonSerializerContext, even if the default converters might have been rooted. + if (!IsInternalConverter && options.SerializerContext is null) + { + result = _fallbackConverterForPropertyNameSerialization; + + if (result is null && DefaultJsonTypeInfoResolver.TryGetDefaultSimpleConverter(TypeToConvert, out JsonConverter? defaultConverter)) + { + Debug.Assert(defaultConverter != this); + _fallbackConverterForPropertyNameSerialization = result = (JsonConverter)defaultConverter; + } + } + + return result; + } + + private JsonConverter? _fallbackConverterForPropertyNameSerialization; + internal virtual T ReadNumberWithCustomHandling(ref Utf8JsonReader reader, JsonNumberHandling handling, JsonSerializerOptions options) => throw new InvalidOperationException(); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index 866690e86677ed..b6872d78575eeb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -246,6 +246,12 @@ public static void ThrowInvalidOperationException_ExpectedString(JsonTokenType t throw GetInvalidOperationException("string", tokenType); } + [DoesNotReturn] + public static void ThrowInvalidOperationException_ExpectedPropertyName(JsonTokenType tokenType) + { + throw GetInvalidOperationException("propertyName", tokenType); + } + [DoesNotReturn] public static void ThrowInvalidOperationException_ExpectedStringComparison(JsonTokenType tokenType) { diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index 42f04dcd271ba7..5ca859459e8898 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -25,6 +25,18 @@ public async Task TestDictionaryKey(Dictionary dicti Assert.Equal(dictionary, deserializedDictionary); } + [Theory] + [MemberData(nameof(GetTestDictionaries))] + public async Task TestDictionaryKey_CustomConverter_ComposingWithDefaultConverter(Dictionary dictionary, string expectedJson) + { + var options = new JsonSerializerOptions { Converters = { new CustomPropertyNameConverter() } }; + string json = await Serializer.SerializeWrapper(dictionary, options); + Assert.Equal(expectedJson, json); + + Dictionary deserializedDictionary = await Serializer.DeserializeWrapper>(json, options); + Assert.Equal(dictionary, deserializedDictionary); + } + public static IEnumerable GetTestDictionaries() { yield return WrapArgs(true, 1); @@ -32,11 +44,18 @@ public static IEnumerable GetTestDictionaries() yield return WrapArgs(char.MaxValue, char.MaxValue, expectedJson: @"{""\uFFFF"":""\uFFFF""}"); yield return WrapArgs(DateTime.MaxValue, 1, expectedJson: $@"{{""{DateTime.MaxValue:O}"":1}}"); yield return WrapArgs(DateTimeOffset.MaxValue, 1, expectedJson: $@"{{""{DateTimeOffset.MaxValue:O}"":1}}"); + yield return WrapArgs(TimeSpan.MaxValue, 1, expectedJson: $@"{{""{TimeSpan.MaxValue}"":1}}"); +#if NET6_0_OR_GREATER + yield return WrapArgs(DateOnly.MaxValue, 1, expectedJson: $@"{{""{DateOnly.MaxValue:O}"":1}}"); + yield return WrapArgs(TimeOnly.MaxValue, 1, expectedJson: $@"{{""{TimeOnly.MaxValue:O}"":1}}"); +#endif yield return WrapArgs(decimal.MaxValue, 1, expectedJson: $@"{{""{JsonSerializer.Serialize(decimal.MaxValue)}"":1}}"); yield return WrapArgs(double.MaxValue, 1, expectedJson: $@"{{""{JsonSerializer.Serialize(double.MaxValue)}"":1}}"); yield return WrapArgs(MyEnum.Foo, 1); yield return WrapArgs(MyEnumFlags.Foo | MyEnumFlags.Bar, 1); yield return WrapArgs(Guid.NewGuid(), 1); + yield return WrapArgs(new Version(8, 0, 0), 1); + yield return WrapArgs(new Uri("http://dot.net/"), 1); yield return WrapArgs(short.MaxValue, 1); yield return WrapArgs(int.MaxValue, 1); yield return WrapArgs(long.MaxValue, 1); @@ -55,6 +74,28 @@ static object[] WrapArgs(TKey key, TValue value, string? expectedJ } } + public class CustomPropertyNameConverter : JsonConverter + { + private readonly JsonConverter _defaultConverter; + + public CustomPropertyNameConverter() + { + _defaultConverter = (JsonConverter)JsonSerializerOptions.Default.GetConverter(typeof(T)); + } + + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => _defaultConverter.Read(ref reader, typeToConvert, options); + + public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => _defaultConverter.ReadAsPropertyName(ref reader, typeToConvert, options); + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + => _defaultConverter.Write(writer, value, options); + + public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + => _defaultConverter.WriteAsPropertyName(writer, value, options); + } + [Theory] [MemberData(nameof(GetUnsupportedDictionaries))] public Task ThrowUnsupported_Serialize(Dictionary dictionary) @@ -80,9 +121,8 @@ public static IEnumerable GetUnsupportedDictionaries() { yield return WrapArgs(new MyPublicClass(), 0); yield return WrapArgs(new MyPublicStruct(), 0); - yield return WrapArgs(new Uri("http://foo"), 0); yield return WrapArgs(new object(), 0); - yield return WrapArgs((object)new Uri("http://foo"), 0); + yield return WrapArgs((object)new MyPublicStruct(), 0); static object[] WrapArgs(TKey key, TValue value) => new object[] { new Dictionary() { [key] = value } }; } @@ -487,4 +527,4 @@ public override void Write(Utf8JsonWriter writer, ClassWithIDictionary value, Js } } #endif -} + } diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs index c6c47a5626038d..98ea68cbdd7d35 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Xunit; @@ -1281,8 +1282,8 @@ public static IEnumerable CustomInterfaces_Dictionaries() [Fact] public async Task IReadOnlyDictionary_NotSupportedKey() { - await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>(@"{""http://foo"":1}")); - await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(new GenericIReadOnlyDictionaryWrapper(new Dictionary { { new Uri("http://foo"), 1 } }))); + await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>(@"{""key"":1}")); + await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(new GenericIReadOnlyDictionaryWrapper(new Dictionary { { JsonNode.Parse("false"), 1 } }))); } } } diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index 85a4f81ddfe164..bf8be277756723 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -1177,8 +1177,8 @@ public async Task JsonIgnoreAttribute_UnsupportedCollection() // Only when the collection contains elements. var dictionary = new Dictionary(); - // Uri is an unsupported dictionary key. - dictionary.Add(new Uri("http://foo"), "bar"); + // ValueTuple is an unsupported dictionary key. + dictionary.Add((0, 1), "bar"); var concurrentDictionary = new ConcurrentDictionary(dictionary); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs index 033fe45d6c8327..5f6d9aaa617fba 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Tests; using System.Threading.Tasks; @@ -131,8 +132,8 @@ public async Task DeserializeAsyncEnumerable() [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(Dictionary>))] [JsonSerializable(typeof(TestClassWithDictionary))] - [JsonSerializable(typeof(IReadOnlyDictionary))] - [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper))] + [JsonSerializable(typeof(IReadOnlyDictionary))] + [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(IReadOnlyDictionary))] [JsonSerializable(typeof(Dictionary))] @@ -238,7 +239,7 @@ public async Task DeserializeAsyncEnumerable() [JsonSerializable(typeof(MyListString))] [JsonSerializable(typeof(NetworkWrapper))] [JsonSerializable(typeof(Client))] - [JsonSerializable(typeof(IReadOnlyDictionary))] + [JsonSerializable(typeof(IReadOnlyDictionary))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(GenericIEnumerableWrapper))] [JsonSerializable(typeof(IEnumerable))] @@ -527,8 +528,8 @@ public CollectionTests_Default() [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(Dictionary>))] [JsonSerializable(typeof(TestClassWithDictionary))] - [JsonSerializable(typeof(IReadOnlyDictionary))] - [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper))] + [JsonSerializable(typeof(IReadOnlyDictionary))] + [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(IReadOnlyDictionary))] [JsonSerializable(typeof(Dictionary))] @@ -634,7 +635,7 @@ public CollectionTests_Default() [JsonSerializable(typeof(MyListString))] [JsonSerializable(typeof(NetworkWrapper))] [JsonSerializable(typeof(Client))] - [JsonSerializable(typeof(IReadOnlyDictionary))] + [JsonSerializable(typeof(IReadOnlyDictionary))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(GenericIEnumerableWrapper))] [JsonSerializable(typeof(IEnumerable))]