System.Text.Json 反序列化 uint

Posted

技术标签:

【中文标题】System.Text.Json 反序列化 uint【英文标题】:System.Text.Json deserialize 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

【问题讨论】:

可能原因:Fields are not supported in System.Text.Json in .NET Core 3.1 另见***.com/q/58139759/5803406 即,您在public uint ModeId; 中缺少get; set;(这是故意的吗?),那么您的转换器可以工作。 -- 不需要= new() uint 工作正常 @Keith Nicholas 是的,在选项中设置NumberHandling = JsonNumberHandling.AllowReadingFromString。或者包括字段,设置IncludeFields = true。这么多的可能性...... 【参考方案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

以上是关于System.Text.Json 反序列化 uint的主要内容,如果未能解决你的问题,请参考以下文章

如何在反序列化之前使用 System.Text.Json 验证 JSON

为啥使用 System.Text.Json 的 JSON 反序列化这么慢?

使用 System.Text.Json 使用动态键查询或反序列化 json

System.Text.Json 反序列化 uint

使用 system.text.json 序列化和反序列化流

System.Text.Json - 将嵌套对象反序列化为字符串