Search code examples
c#jsonjson.net

How to return NULL from JsonConvert.DeserializeObject


I have a class:

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

Then I'm trying to deserialize JSON string to this class:

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

My JSON string for example:

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

As a result I have an object which have all properties is NULL, but customResponse is not NULL. How do I get NULL in result?


Solution

  • You could create a custom JsonConverter that allocates and populates your object, then checks afterwards to see whether all properties are null, using the value returned by the 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();
        }
    }
    

    Then use it like:

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

    Sample fiddle.

    However, in comments you wrote, if CustomResponse is NULL, then service return a correct response and i try to deserialize to OtherCustomResponse. In that case, consider using a polymorphic converter such as the ones from How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects? or Deserializing polymorphic json classes without type information using json.net