[英]Deserialize false as null (System.Text.Json)
I'm using an API which for some reason uses false where it should be using null.我正在使用一个 API,它出于某种原因在应该使用 null 的地方使用了 false。 I can't figure out how to deserialize this properly.
我不知道如何正确反序列化。 I tried to create a custom JsonConverter to solve this, but was unable to do so.
我试图创建一个自定义 JsonConverter 来解决这个问题,但无法这样做。 I'd like to avoid using the dynamic type.
我想避免使用动态类型。 How should I deserialize this?
我应该如何反序列化这个?
This is the default response.这是默认响应。
{
"products": [
{
"id": 123456789,
"supplier": {
"id": 123456,
"title": "abc"
}
}
]
}
Which I am deserializing as following.我正在反序列化如下。
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)
And this is the response when there is no supplier for the product.这是当产品没有供应商时的反应。
{
"products": [
{
"id": 123456789,
"supplier": false
}
]
}
You can create your custom JsonConverter
for the supplier
property:您可以为
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;
}
}
Update:更新:
If you are using System.Text.Json
, you can try the following custom converter:如果您使用
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();
}
}
When using System.Text.Json
, you can implement and register your own JsonConverter<T>
for the Supplier
property.使用
System.Text.Json
,您可以为Supplier
属性实现和注册您自己的JsonConverter<T>
。
There are two ways you can consider implementing your converter, depending on your need (whether you need to use the Supplier
object in multiple places OR if you need to use different JsonSerializerOption
settings or not).有两种方法可以考虑实现转换器,具体取决于您的需要(是否需要在多个位置使用
Supplier
对象,或者是否需要使用不同的JsonSerializerOption
设置)。
JsonConverter<Supplier>
and add the custom logic to handle false
.JsonConverter<Supplier>
并添加自定义逻辑来处理false
。 Leave the rest to the Deserialize
call.Deserialize
调用。 In your implementation, do not pass in options.// 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>
and add the custom logic to handle "false" along with the deserialization of the Supplier
object.JsonConverter<Supplier>
并添加自定义逻辑来处理“false”以及Supplier
对象的反序列化。 In this case, you can register this converter either within the options, or use it as an attribute on the Supplier
class itself.Supplier
类本身的属性。 Follow this approach if you need to use custom options settings for deserializing the supplier for some reason (such as case insensitive matching of the property names).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.
This doc will be useful to you when writing custom converters:在编写自定义转换器时,此文档对您很有用:
https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
Here are the relevant API docs:以下是相关的 API 文档:
Here's a working example (for both when the json contains a false
supplier and when it contains the actual supplier
JSON object in the payload): https://dotnetfiddle.net/XFbXB1这是一个工作示例(对于当 json 包含
false
供应商以及当它在有效负载中包含实际supplier
JSON 对象时): https : //dotnetfiddle.net/XFbXB1
Assuming you are using Json.Net假设您使用的是 Json.Net
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Include;
settings.DefaultValueHandling = DefaultValueHandling.Include;
JsonSerializer.Deserialize<Container>(json,settings)
or try或尝试
var serializeOptions = new JsonSerializerOptions
{
IgnoreNullValues =false
};
JsonSerializer.Deserialize<Container>(json,serializeOptions)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.