如何从JsonConvert.DeserializeObject中返回NULL

3

我有一个类:

public class CustomResponse
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string Message {get; set; }
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string Details {get; set; }
}

然后,我尝试将JSON字符串反序列化为这个类:

var settings = new JsonSerializerSettings
    {
        NullValueHandling.Ignore,
        MissingMemberHandling.Ignore,
    };
var customResponse = JsonConvert.Deserialize<CustomResponse>(jsonString, settings);

例如我的JSON字符串:

{"DocumentId":"123321", "DocumentNumber":"ABC123"}

因此,我有一个对象,其中所有属性都为NULL,但customResponse不为NULL。如何在结果中获得NULL?

1
你需要一个自定义的JsonConverter来实现这个功能。 - dbc
你为什么会期望customResponsenull呢? - Daniel A. White
也许 CustomResponse 可以有一个计算/只读属性,比如 IsEmptyIsValid,用于检测其是否有效。 - Daniel A. White
如果CustomResponse为NULL,则服务返回一个正确的响应,我尝试对其进行反序列化以获取OtherCustomResponse。 - Aleksandr Zharinov
@dbc 谢谢,这是一个不错的选择。我会尝试的。 - Aleksandr Zharinov
显示剩余5条评论
2个回答

3

如果您想避免创建自定义的JsonConverter,可以使用以下扩展方法:

public static class Exts
{
    public static T OrDefaultWhen<T>(this T obj, Func<T, bool> predicate)
    {
        return predicate(obj) ? default(T) : obj;
    }
}

使用方法:

var jsonString = @"{
    Message: null,
    Details: null
}";

var res = JsonConvert.DeserializeObject<CustomResponse>(jsonString)
                     .OrDefaultWhen(x => x.Details == null && x.Message == null);

谢谢,这个也可以,但我更喜欢另一种选项。 - Aleksandr Zharinov

2
你可以创建一个自定义的 JsonConverter,来分配并填充你的对象,然后在之后检查所有属性是否为空,使用JsonProperty.ValueProvider返回的值:
public class ReturnNullConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        // Get the contract.
        var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);

        // Allocate the object (it must have a parameterless constructor)
        existingValue = existingValue ?? contract.DefaultCreator();

        // Populate the values.
        serializer.Populate(reader, existingValue);

        // This checks for all properties being null.  Value types are never null, however the question
        // doesn't specify a requirement in such a case.  An alternative would be to check equality
        // with p.DefaultValue
        // http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_DefaultValue.htm
        if (contract.Properties
            .Where(p => p.Readable)
            .All(p => object.ReferenceEquals(p.ValueProvider.GetValue(existingValue), null)))
            return null;

        return existingValue;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后像这样使用它:
var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore,
    Converters = { new ReturnNullConverter<CustomResponse>() },
};
var customResponse = JsonConvert.DeserializeObject<CustomResponse>(jsonString, settings);

样例 fiddle
然而,在您的评论中,您写道:如果CustomResponse为NULL,则服务返回正确的响应,并尝试反序列化为OtherCustomResponse。在这种情况下,考虑使用多态转换器,例如来自如何在JSON.NET中实现自定义JsonConverter以反序列化基类对象列表?使用json.net反序列化多态json类而不使用类型信息的转换器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接