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 指出的那样 - 安装 <PackageReference Include="System.Text.Json" Version="5.0.2" />
,那么您可以使用 IncludeFields
和 AllowReadingFromString
选项:
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 反序列化这么慢?