給定這個模型類:
using System.Text.Json;
public class QueueMessage
{
public int MerchantId { get; }
public string Message { get; }
}
當我嘗試將 json 字串反序列化為 QueueMessage 型別時,這些欄位設定為默認值。0 和空。這就是我嘗試反序列化它的方式:
var jsonString = "{\"MerchantId\":2,\"Message\":\"Message 2\"}";
QueueMessage message = JsonSerializer.Deserialize<QueueMessage>(jsonString, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
message.Message is null
message.MerchantId is 0
順便說一句,我正在使用.Net 5。
我嘗試了什么 好吧,我嘗試使用我的老朋友 Newtonsoft.Json
dynamic message = JsonConvert.DeserializeObject(jsonString);
dynamic mercId = message.MerchantId.Value; //THIS gives the expected value of 2
然而,
QueueMessage msg = JsonConvert.DeserializeObject<QueueMessage>(jsonString);
給出 0, null 結果
現在,問題是為什么反序列化到型別化物件會失敗?
uj5u.com熱心網友回復:
作為 Ziv 答案的替代方案,如果您重視構造型別和/或不變性的好處,
System.Text.Json現在支持的最新版本\[JsonConstructor\],因此您現在可以使用構造的 DTO 型別。在我看來,您還應該始終指定顯式
[JsonPropertyName]以防止因重命名屬性或更改專案范圍camelCase與PascalCaseJSON 序列化設定而導致的 DTO/JSON 損壞。- 我也認為 JSON 物件成員應該始終使用
camelCase,而不是PascalCaseJavaScript/TypeScript 使用的大寫約定,這是 JSON 型別的常用目標(不幸的是,STJ 默認為PascalCase(*grrrr*))
- 我也認為 JSON 物件成員應該始終使用
示例 1:使用簡單的建構式
- ...雖然這不是一個很好的例子,因為它并沒有顯示 ctor 實際上做了任何有用的事情。
using System.Text.Json;
public class QueueMessage
{
[JsonConstructor]
public QueueMessage(
int merchantId,
string? message
)
{
this.MerchantId = merchantId;
this.Message = message;
}
[JsonPropertyName("merchantId")] public int MerchantId { get; }
[JsonPropertyName("message") ] public string? Message { get; }
}
示例 2:使用驗證建構式
- 因為建構式可以進行斷言和驗證引數,這意味著 ctor 可以防止
QueueMessage.Message永遠存在null,所以String?可以將屬性更改為String更好地使用 DTO - 它也可以驗證MerchantId:
using System.Text.Json;
public class QueueMessage
{
[JsonConstructor]
public QueueMessage(
int merchantId,
string message
)
{
this.MerchantId = merchantId > 0 ? merchantId : throw new ArgumentOutOfRangeException( paramName: nameof(merchantId), actualValue: merchantId, message: "Value must be positive and non-zero." );
this.Message = message ?? throw new ArgumentNullException(nameof(message));
}
/// <summary>Always >= 1.</summary>
[JsonPropertyName("merchantId")] public int MerchantId { get; }
/// <summary>Never null.</summary>
[JsonPropertyName("message") ] public string Message { get; }
}
示例 3:使用record class
- 為了簡單起見,您也可以只使用
record class.- 雖然這失去了驗證邏輯,但
Message現在String?又是這樣。
- 雖然這失去了驗證邏輯,但
- 使用語法通過其 ctor 引數名稱
[property: ]將JsonPropertyName其他屬性應用于屬性。record class
public record class QueueMessage(
[property: JsonPropertyName("merchantId")] int MerchantId,
[property: JsonPropertyName("message") ] string? Message
);
uj5u.com熱心網友回復:
您需要將設定器添加到您的屬性,否則反序列化程式無法為這些屬性分配值
public class QueueMessage
{
public int MerchantId { get; set; }
public string Message { get; set; }
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/443567.html
上一篇:使用Jackson從JSONAPI回應生成不同的Java物件
下一篇:自動密鑰加密
