Closed
Description
Description
Deserializing a number to a property of type System.UInt16
fails when using JsonTypeInfo<T>
. The same JSON string can be deserialized when using other integral types or reflection.
The generated code for UInt16
(see below) looks odd compared to the generated source for other value types. The UInt16
getter calls CreateObjectInfo<T>
instead of CreateValueInfo<T>
in the else branch.
I reckon that is because UInt16
is not added to _numberTypes
here (UInt64
is added twice though):
runtime/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
Lines 1043 to 1057 in 71f9191
InfoCtx.UInt16.g.cs
:
namespace stj_ushort
{
internal sealed partial class InfoCtx
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.UInt16> _UInt16;
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.UInt16> UInt16
{
get
{
if (_UInt16 == null)
{
global::System.Text.Json.Serialization.JsonConverter customConverter;
if (Options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(typeof(global::System.UInt16))) != null)
{
_UInt16 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.UInt16>(Options, customConverter);
}
else
{
_UInt16 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::System.UInt16>(
Options,
createObjectFunc: static () => new global::System.UInt16(),
propInitFunc: UInt16PropInit,
default,
serializeFunc: null);
}
}
return _UInt16;
}
}
private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] UInt16PropInit(global::System.Text.Json.Serialization.JsonSerializerContext context)
{
global::stj_ushort.InfoCtx jsonContext = (global::stj_ushort.InfoCtx)context;
global::System.Text.Json.JsonSerializerOptions options = context.Options;
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[0];
return properties;
}
}
}
Configuration
Windows 10 x64
.NET SDK 6.0.100-preview.6.21355.2
System.Text.Json 6.0.0-rc.1.21403.3
Repro
using System.Text.Json; // 6.0.0-rc.1.21403.3
using System.Text.Json.Serialization;
using Xunit;
namespace stj_ushort {
internal sealed class InfoUshort { public ushort Port { get; set; } }
internal sealed class InfoShort { public short Port { get; set; } }
internal sealed class InfoByte { public byte Port { get; set; } }
[JsonSerializable(typeof(InfoUshort), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(InfoShort), GenerationMode = JsonSourceGenerationMode.Metadata)]
internal sealed partial class InfoCtx : JsonSerializerContext { }
public class UnitTest1 {
private const byte Expected = 42;
private static readonly string JsonString = "{\"Port\":42}";
private static readonly byte[] JsonBytes = System.Text.Encoding.ASCII.GetBytes(JsonString);
[Fact] // Red, System.Text.Json.JsonException: The JSON value could not be converted to System.UInt16. Path: $.port | LineNumber: 0 | BytePositionInLine: 10.
public void Deserialize_Ushort() {
InfoUshort result = JsonSerializer.Deserialize(JsonBytes, InfoCtx.Default.InfoUshort);
Assert.Equal(Expected, result.Port);
}
[Fact] // Green
public void Deserialize_Short() {
InfoShort result = JsonSerializer.Deserialize(JsonBytes, InfoCtx.Default.InfoShort);
Assert.Equal(Expected, result.Port);
}
[Fact] // Green
public void Deserialize_Ushort_Reflection() {
InfoUshort result = JsonSerializer.Deserialize<InfoUshort>(JsonBytes);
Assert.Equal(Expected, result.Port);
}
}
}
Stack trace
System.Text.Json.JsonException: The JSON value could not be converted to System.UInt16. Path: $.Port | LineNumber: 0 | BytePositionInLine: 10.
System.Text.Json.JsonException
The JSON value could not be converted to System.UInt16. Path: $.Port | LineNumber: 0 | BytePositionInLine: 10.
at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType) in System.Text.Json.dll:token 0x6000100+0x18
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x6000a51+0x22
at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x600097e+0x24
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x60007b5+0x197
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader) in System.Text.Json.dll:token 0x60008e4+0xdb
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x6000a51+0x90
at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x600097e+0x24
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) in System.Text.Json.dll:token 0x60007b5+0x197
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) in System.Text.Json.dll:token 0x60007a1+0xbf
at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) in System.Text.Json.dll:token 0x60003bc+0xa
at System.Text.Json.JsonSerializer.ReadUsingMetadata[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount) in System.Text.Json.dll:token 0x60003bd+0x2f
at System.Text.Json.JsonSerializer.Deserialize[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo`1 jsonTypeInfo) in System.Text.Json.dll:token 0x60003c0+0xe
at stj_ushort.UnitTest1.Deserialize_Ushort()