Search code examples
c#jsonuwpjson.netuwp-xaml

JSON deserialized object returns null


Source Code - Main class

        string responseBody = await response.Content.ReadAsStringAsync();

        status.result deserializeObject = JsonConvert.DeserializeObject<status.result>(responseBody);

        Debug.WriteLine(deserializeObject.SafeGasPrice.ToString());

Source Code - JSON Class

    public class status
    {
        public class result
        {
            [JsonProperty(PropertyName = "SafeGasPrice")]
            public int SafeGasPrice { get; set; }

            [JsonProperty(PropertyName = "ProposeGasPrice")]
            public int ProposeGasPrice { get; set; }

            [JsonProperty(PropertyName = "FastGasPrice")]
            public int FastGasPrice { get; set; }
        }
    }

Output

{"status":"1","message":"OK","result":{"LastBlock":"14296250","SafeGasPrice":"96","ProposeGasPrice":"96","FastGasPrice":"97","suggestBaseFee":"95.407119606","gasUsedRatio":"0.174721033333333,0.523179548504219,0.056945596868572,0.999939743363228,0.953861217484817"}}

0

Problem

I don't currently understand why a null is output, my guess is that I have implemented the json deserialization classes incorrectly.


Solution

  • Your data model does not correspond to the JSON provided, it is missing a type corresponding to the outer {"result": { }} object:

    {
       "status":"1",
       "message":"OK",
       "result":{
          // This inner object corresponds to your model.
          "LastBlock":"14296250",
          "SafeGasPrice":"96",
          "ProposeGasPrice":"96",
          "FastGasPrice":"97",
          "suggestBaseFee":"95.407119606",
          "gasUsedRatio":"0.174721033333333,0.523179548504219,0.056945596868572,0.999939743363228,0.953861217484817"
       }
    }
    

    To work around the problem, you need to introduce an outer, wrapper model. You could make an explicit one like so:

    public class Root
    {
        public string status { get; set; }
        public string message { get; set; }
        public Result result { get; set; }
    }
    
    public class Result
    {
        [JsonProperty(PropertyName = "SafeGasPrice")]
        public int SafeGasPrice { get; set; }
    
        [JsonProperty(PropertyName = "ProposeGasPrice")]
        public int ProposeGasPrice { get; set; }
    
        [JsonProperty(PropertyName = "FastGasPrice")]
        public int FastGasPrice { get; set; }
    }
    

    And deserialize like so:

    var deserializeObject = JsonConvert.DeserializeObject<Root>(responseBody)?.result;
    

    Or, you could use an anonymous type for the root model like so:

    var deserializeObject = JsonConvert.DeserializeAnonymousType(responseBody, new { result = default(Result) })?.result;
    

    Either way you will now be able to successfully deserialize the inner, nested properties.

    So what did you do wrong? In your question, you declare result as a nested type:

    public class status
    {
        public class result
        {
            [JsonProperty(PropertyName = "SafeGasPrice")]
            public int SafeGasPrice { get; set; }
    
            [JsonProperty(PropertyName = "ProposeGasPrice")]
            public int ProposeGasPrice { get; set; }
    
            [JsonProperty(PropertyName = "FastGasPrice")]
            public int FastGasPrice { get; set; }
        }
    }
    

    All this does is define a type result within the scope of another type status. It does not create a property named result within status. As there is no need for such nesting I recommend moving result out from inside status and renaming it Result to follow standard .NET naming conventions.

    Demo fiddle here.