【问题标题】:System.Text.Json deserialize uintSystem.Text.Json 反序列化 uint
【发布时间】:2021-07-17 04:22:16
【问题描述】:

因此,新的 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。我尝试根据我找到的单元测试添加自定义转换器 here 像这样:

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 属性的序列化/反序列化,您有什么建议/建议?

[更新]:问题在于我试图序列化/反序列化一个字段,而不是答案中指出的具有公共访问器的属性。恰好该字段的类型为uint

【问题讨论】:

标签: c# json asp.net-mvc json-deserialization system.text.json


【解决方案1】:

如果您使用的是 .NET 5,或者 - 正如 @Jimi 指出的那样 - 安装 &lt;PackageReference Include="System.Text.Json" Version="5.0.2" /&gt;,那么您可以使用 IncludeFieldsAllowReadingFromString 选项:

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 开始)。

【讨论】:

  • 这当然是正确的,但重要的不是 .Net 版本,而是 System.Text.Json 版本。您也可以将 v.5.0.2 添加到 .Net Framework,只需获取 NuGet Package
  • 感谢两位提供的线索。 Jimi 指出的问题是领域。事实证明,它不需要您指出的转换器。我正在使用 .net5 和 System.Text.Json 5.0.2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 2020-06-23
  • 1970-01-01
相关资源
最近更新 更多