[英]Deserialize false as null (System.Text.Json)
我正在使用一個 API,它出於某種原因在應該使用 null 的地方使用了 false。 我不知道如何正確反序列化。 我試圖創建一個自定義 JsonConverter 來解決這個問題,但無法這樣做。 我想避免使用動態類型。 我應該如何反序列化這個?
這是默認響應。
{
"products": [
{
"id": 123456789,
"supplier": {
"id": 123456,
"title": "abc"
}
}
]
}
我正在反序列化如下。
public class Container
{
public Product[] products { get; set; }
}
public class Product
{
public ulong id { get; set; }
public Supplier supplier { get; set; }
}
public class Supplier
{
public ulong id { get; set; }
public string title { get; set; }
}
JsonSerializer.Deserialize<Container>(json)
這是當產品沒有供應商時的反應。
{
"products": [
{
"id": 123456789,
"supplier": false
}
]
}
您可以為supplier
屬性創建自定義JsonConverter
:
public class Product
{
public ulong id { get; set; }
[JsonConverter(typeof(SupplierConverter))]
public Supplier supplier { get; set; }
}
public class SupplierConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Boolean)
{
if ((bool)reader.Value == false)
return null;
}
return serializer.Deserialize(reader, objectType);
}
public override bool CanConvert(Type objectType)
{
return false;
}
}
更新:
如果您使用System.Text.Json
,您可以嘗試以下自定義轉換器:
public class SupplierConverter : JsonConverter<Supplier>
{
public override Supplier Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
return null;
if (options.GetConverter(typeof(JsonElement)) is JsonConverter<JsonElement> converter)
{
var json = converter.Read(ref reader, typeToConvert, options).GetRawText();
return JsonSerializer.Deserialize<Supplier>(json);
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, Supplier value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
使用System.Text.Json
,您可以為Supplier
屬性實現和注冊您自己的JsonConverter<T>
。
有兩種方法可以考慮實現轉換器,具體取決於您的需要(是否需要在多個位置使用Supplier
對象,或者是否需要使用不同的JsonSerializerOption
設置)。
JsonConverter<Supplier>
並添加自定義邏輯來處理false
。 剩下的交給Deserialize
調用。 在您的實現中,不要傳入選項。 然后,在選項中注冊此轉換器。 這是最簡單的方法。// Don't register this converter using an attribute on the Supplier class
// since you are calling Deserialize on this type directly within the converter.
public class SupplierConverter : JsonConverter<Supplier>
{
public override Supplier Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null;
}
// Skip passing options here to avoid stackoverflow
// This approach won't work if you have other options that need to be honored
// when deserializing Supplier.
return JsonSerializer.Deserialize<Supplier>(ref reader);
}
public override void Write(
Utf8JsonWriter writer,
Supplier value,
JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
// Register the converter within options as follows
// and pass the options the JsonSerializer.Deserialize call.
var options = new JsonSerializerOptions
{
Converters = {new SupplierConverter()}
};
JsonConverter<Supplier>
並添加自定義邏輯來處理“false”以及Supplier
對象的反序列化。 在這種情況下,您可以在選項中注冊此轉換器,也可以將其用作Supplier
類本身的屬性。 如果出於某種原因(例如不區分大小寫的屬性名稱匹配)需要使用自定義選項設置來反序列化供應商,請遵循此方法。public class SupplierConverter : JsonConverter<Supplier>
{
public override Supplier Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
// Put whatever special case condition here.
// I added a null token check as well, just in case.
if (reader.TokenType == JsonTokenType.False
|| reader.TokenType == JsonTokenType.Null)
{
return null;
}
var output = new Supplier();
// Potentially add other error handling for invalid JSON, if needed.
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
if (reader.ValueTextEquals("id"))
{
if (!reader.Read()) throw new JsonException();
output.id = reader.GetUInt64();
}
else if (reader.ValueTextEquals("title"))
{
if (!reader.Read()) throw new JsonException();
output.title = reader.GetString();
}
}
}
if (reader.TokenType != JsonTokenType.EndObject)
{
throw new JsonException();
}
return output;
}
public override void Write(
Utf8JsonWriter writer,
Supplier value,
JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
// Register the converter within options as follows
// and pass the options the JsonSerializer.Deserialize call.
var options = new JsonSerializerOptions
{
Converters = {new SupplierConverter()}
};
// OR
// Use annotate your Supplier class with
// a JsonConverterAttribute.
在編寫自定義轉換器時,此文檔對您很有用:
https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
以下是相關的 API 文檔:
這是一個工作示例(對於當 json 包含false
供應商以及當它在有效負載中包含實際supplier
JSON 對象時): https : //dotnetfiddle.net/XFbXB1
假設您使用的是 Json.Net
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Include;
settings.DefaultValueHandling = DefaultValueHandling.Include;
JsonSerializer.Deserialize<Container>(json,settings)
或嘗試
var serializeOptions = new JsonSerializerOptions
{
IgnoreNullValues =false
};
JsonSerializer.Deserialize<Container>(json,serializeOptions)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.