skip to Main Content

C# with Newtonsoft.Json 13.0.2. I am deserializing a JSON string as such

var car = JsonConvert.DeserializeObject<Car>(resp);

where resp looks like this:

{
    "perf": {
        "perfRef": null,
        "perfTest": {
            "value": 1.2,
            "unit": "percent"
        }
    }
}

My class looks like this:

public partial class perf
{
    [Newtonsoft.Json.JsonProperty("perfRef", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public PerfRef perfRef { get; set; }

    [Newtonsoft.Json.JsonProperty("perfTest", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public PerfTest perfTest { get; set; }

}

But I keep getting an exception

Newtonsoft.Json.JsonSerializationException: Required property 'perfRef' expects a non-null value. Path 'perf'

I don’t get why this is happening. I thought the NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore would override any ‘Required’ option. Am I just misinterpreting how the decorators work?

2

Answers


  1. you have Required which means you cannot have a null value for the perfRef
    property.

    there are ways to solve this.

    either remove Required or provide the value to this property or set the Required attribute to AllowNull or Default.

    Note: NullValueHandling Ignore means that null values will be ignored when serializing and deserializing JSON.

    Login or Signup to reply.
  2. Could it be that the cause is that the json-string is wrapped with {"Perf": {...}} and you need an additional class to deserialize it.

    My sample array [...] has two json-strings. Both contain the same object {...}

    • the first wraps it with {"Perf": {...}} like your sample
    • the second does not.
    [
    {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}},        
             {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
    ]
    
    

    You can deserialize the first json string json[0] = {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}} using a class that acts as a wrapper (here JsonResponse):

    // to deserialize 
    // {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}}
    public class JsonResponse{
        public Perf Perf {get; set;}
    }
    
    // use
    JsonResponse resp0 = JsonConvert.DeserializeObject<JsonResponse>(json[0]); 
    

    If the json-string would not be wrapped then there is no need for a wrapper class

    // to deserialize json[1] 
    // {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
    
    // use
    Perf resp1 = JsonConvert.DeserializeObject<Perf>(json[1]); 
    

    This is a -program that deserializes both json strings:

    void Main()
    {   
        // for {"Perf": {...}} a wrapper class is needed
        JsonResponse withWrap = JsonConvert.DeserializeObject<JsonResponse>(GetResp()[0]); 
    
        // for {...} not
        Perf noWrap = JsonConvert.DeserializeObject<Perf>(GetResp()[1]); 
        withWrap.Dump("Object {...} wrapped in JsonResponse: {Perf: {...}}");
        noWrap.Dump("Object {...} not wrapped");
    }
    // You can define other methods, fields, classes and namespaces here
    public string[] GetResp(){
        string[] responses = {""" 
            {"Perf":{"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}}
            """, 
            """ 
            {"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}
            """};
        return responses;
    }
    public class JsonResponse{
        public Perf Perf {get; set;}
    }
    public class PerfTest{
        public string? Unit {get; set;}
        public double? Value {get; set;}    
    }
    public class Perf{ 
        [Newtonsoft.Json.JsonProperty("perfRef")]
        public string PerfRef { get; set; }
        //public PerfRef perfRef { get; set; }
    
        [Newtonsoft.Json.JsonProperty("perfTest")]
        public PerfTest PerfTest { get; set; }
    }
    

    The result of the deserialized object JsonResponse and Perf are on the right side.

    linqpad newtonsoft serialize with wrapper JsonResponse

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search