首页 > 解决方案 > System.Text.Json 反序列化 uint

问题描述

所以看起来新的 Json 库没有反序列化(甚至为此序列化)UInt32类型。在 MVC 应用程序中,以下内容在 POST 的有效负载中发送:

{
   "Overrides":{
      
   },
   "Directions":{
      "data1" : "data2"
   },   
   "ModeId": "1782354543",
   "TestNumber" : 10
}

它应该被序列化的类是这样的:

public class Payload
    {
        public uint ModeId;
        public Dictionary<string, string> Directions{ get; set; } = new();
        public Dictionary<string, string> Overrides { get; set; } = new();
        public int TestNumber { get; set; }
    }

但是当收到请求时,ModeId为 0。我尝试根据我在这里找到的单元测试添加自定义转换器 像这样:

public class UIntConverter : JsonConverter<uint>
    {
        public override uint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                string stringValue = reader.GetString();
                if (uint.TryParse(stringValue, out uint x))
                {
                    return x;
                }
            }
            if (reader.TokenType == JsonTokenType.Number)
            {
                return reader.GetUInt32();
            }

            throw new JsonException();
        }

        public override void Write(Utf8JsonWriter writer, uint value, JsonSerializerOptions options)
        {
            writer.WriteNumberValue(value);
        }
    }

并像这样注册它:

services.AddControllers()
                .AddJsonOptions(options =>
                {
                    options.JsonSerializerOptions.WriteIndented = false;
                    options.JsonSerializerOptions.IgnoreNullValues = true;
                    options.JsonSerializerOptions.PropertyNamingPolicy = null;
                    options.JsonSerializerOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
                    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
                    options.JsonSerializerOptions.Converters.Insert(options.JsonSerializerOptions.Converters.Count,new UIntConverter());

                });

我什至无法使用相同的转换器将我的类序列化为字符串。它只是忽略了 uid 属性。

var payload = new Payload()
{
   Directions = new Directions
   {
     {"data1", "data2" }
   },
   ModeId = 1782354543,
   TestNumber = 10
}
//then try to serialize
var defaultJsonSerializerSettings = new JsonSerializerOptions()
        {
            IgnoreNullValues = true,
            WriteIndented = false,
            PropertyNamingPolicy = null,
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            Converters = { new UIntConverter()}            
        };
Serializer.Serialize(payload, typeof(Payload), defaultJsonSerializerSettings); 

它序列化所有内容,除了完全被忽略的 uint 属性。

您对 uint 属性的序列化/反序列化有何建议/建议?

[更新]:问题是我试图序列化/反序列化一个字段,而不是答案中指出的具有公共访问器的属性。碰巧 field 是 type uint

标签: c#jsonasp.net-mvcjson-deserializationsystem.text.json

解决方案


如果您使用的是 .NET 5,或者如果 - 正如@Jimi 指出的那样 - install <PackageReference Include="System.Text.Json" Version="5.0.2" />,则可以使用IncludeFieldsandAllowReadingFromString选项:

var serializeOptions = new JsonSerializerOptions
{
    IncludeFields = true,
    NumberHandling = JsonNumberHandling.AllowReadingFromString
};

var p = JsonSerializer.Deserialize<Payload>(json, serializeOptions);

在 .NET5 之前,您需要将 ModeId 更改为属性。


顺便提一句。您可以在没有转换器的情况下处理字符串/整数:

public string ModeId {get; set}
public uint ModeIdParsed => uint.Parse(ModeId);

如果你需要保留ModeId名字,那么你可以

public class Payload
{
   [JsonPropertyName("ModeId")]
   public string modeId {get;set;}

   [JsonIgnore]
   public uint ModeId => uint.Parse(modeId);
}

不幸的是,在 3.1 中,您需要将字符串变体公开(反序列化私有可从 v5 获得)。


推荐阅读