none
Error deserializing a JSON response RRS feed

  • Question

  • Hello,

    I am trying to get the following JSON response into a list so I can reference on value and get another :

    {
        "Result": [
            {
                "Key": "19e848a2-cbb6-4c72-8e24-05ce47da7754",
                "Name": "Bistro"
            },
            {
                "Key": "d274591a-06fd-4d50-a973-5a629a3a6d3a",
                "Name": "Sports Bar"
            },
            {
                "Key": "b648abd8-da53-4089-a7f9-5ef7ddece38c",
                "Name": "Constable Suite"
            },
            {
                "Key": "69a4b8b9-427d-4cca-b62a-62e6cbc8a27c",
                "Name": "Haywain Suite"
            },
            {
                "Key": "142a6bc3-86ac-4953-a022-8641f318ffa0",
                "Name": "Hotel Lounge Main Bar"
            },
            {
                "Key": "6294ae4e-273b-408a-8e5f-df5853badf90",
                "Name": "Garden Room"
            },
            {
                "Key": "f0516ab6-9bce-4f35-aa40-f8f49c464023",
                "Name": "Gallery Grill"
            }
        ],
        "RID": "1",
        "CloudDateTime": "2020-07-04T08:16:36.0000000Z",
        "Success": true,
        "Message": ""
    }

    and I have defined my classes as

    public class Dept
    {
      public Result _Result { get; set; }
      public string _RID { get; set; }
      public DateTime _CloudDateTime { get; set; }
      public bool _Success { get; set; }
      public string _Message { get; set; }
    }
    
    public class Result
    {
      public string _Key { get; set; }
      public string _Name { get; set; }
    }


    but, when i use the following to grab the data :

    List<Dept> Departments = JsonConvert.DeserializeObject<List<Dept>>(response.Content);
                
    foreach (var item in Departments)
                    {
                    var _Key = item._Result._Key;
                    var _Name = item._Result._Name;
                    richTextBox5.AppendText(_Key + " - " + _Name + Environment.NewLine);
                    }

    I get the message

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[myprogram.Form1+Dept]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
    To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
    Path 'Result', line 1, position 10.

    if I change          public Results _Result {get; set;}             to             public List<Result> _Result { get; set; }

    I then get swiggles un der _Key and _Name

                    var _Key = item._Result._Key;
                    var _Name = item._Result._Name;

    saying "does not contain a definition for "_Key" ...."

    How do I get eh response into a list so I can then reference the name to the key  ie : 

    if(_Name == "Bistro")
    {
    var deptKey = theCorrespondingDeptKeyFromList
    MessageBox.show(_Name + " " + deptKey)
    }

    thanks :-)

    Saturday, July 4, 2020 8:30 AM

Answers

  • The code I posted does not line up with the error you're posting so it isn't the code I gave you.

    var dept = JsonConvert.DeserializeObject<Dept>(response.Content>();

    Notice the error message.

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[myprogram.Form1+Dept]'

    This is the same error you were getting before. The error says you're trying to read List<Dept> but the code I gave you is using `Dept`. The error clearly is not coming from that code. There are a couple of possibilities.

    1. There are compiler errors in your code but you have told the IDE to ignore the errors so since the code doesn't compile the debugger is running an older version of your code and hence producing the same runtime error. You need to fix the compiler errors and ultimately you should never agree to the prompts from the IDE to "run code anyway". 

    2. Your original code is still being executed and therefore producing the same error. The stack trace on the error will tell you exactly what line is producing the error so you can diagnose this quickly.

    I can verify that the code I gave you works correctly. I've taken the method I gave you put it into a simple console app that loads the JSON you posted from a file and prints out the result. I also took your original types that you gave. 

    using System;
    using System.Collections.Generic;
    using System.IO;
    
    using Newtonsoft.Json;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main ( string[] args )
            {
                var json = File.ReadAllText("test.json");
    
                var results = GetResults(json);
                foreach (var result in results)
                    Console.WriteLine($"{result.Key} = {result.Name}");
            }
    
            static IEnumerable<Result> GetResults ( string content )
            {   
                //NOTE: Your JSON says there is a single department...
                var dept = JsonConvert.DeserializeObject<Dept>(content);
    
                return dept.Result;
            }
        }
    
        public class Dept
        {
            public List<Result> Result { get; set; }
            public string RID { get; set; }
            public DateTime CloudDateTime { get; set; }
            public bool Success { get; set; }
            public string Message { get; set; }
        }
    
        public class Result
        {
            public string Key { get; set; }
            public string Name { get; set; }
        }
    }
    

    As discussed in the previous post your `Result` property needs to be a list to line up with the JSON so I made that change. However when you run the code you'll not get a valid result back. You likely haven't seen this problem yet because of the earlier error but as I mentioned you are not following standard conventions for properties and therefore the serializer cannot map your non-standard property names to the corresponding JSON fields. While you could annotate the types to get it to work or set up some defaults with the serializer, the more appropriate option is to follow the standard .NET casing conventions (Pascal). So I made that change to your types as well. With those 2 changes in place the JSON is properly read.

    Review your code for the issues I mentioned earlier and adjust your data types as I showed here and the JSON will load properly.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by G-Oker Friday, July 10, 2020 7:32 AM
    Sunday, July 5, 2020 6:48 PM
    Moderator

All replies

  • `Result` in `Dept` is defined as a single object but the JSON has `Result` defined as an array. You need to make your `Result` property in `Dept` an array.

    public class Dept
    {
       public List<Result> _Result {get;set;}
    }

    Note that using _ in a public property is not conformant with standard C# practices. The fact that the serializer even hooked everything up properly is because of some naming convention that was configured. You should really follow standard naming conventions to make your code more resilient to default convention changes in the serializer, or be explicit about the conventions you're using.

    "I then get swiggles un der _Key and _Name"

    Yes that is because your code is making the assumption that there is a single result for each department but the JSON says there can be multiple. Therefore you need to update your code to support the fact that a department can have multiple results. If you don't care about the output department stuff (RID, etc) then don't use that type in your code (outside deserialization), just use the underlying results.

    IEnumerable<Result> GetResults ()
    {
       ...
    
       //NOTE: Your JSON says there is a single department...
       var dept = JsonConvert.DeserializeObject<Dept>(response.Content>();
    
       return dept.Result;
    }
    Note also that you were reading a `List<Dept>` but your root JSON is a single object so it is just `Dept`.


    Michael Taylor http://www.michaeltaylorp3.net

    Saturday, July 4, 2020 2:48 PM
    Moderator
  • Hi CoolDadTX,

    I try the code you posted

                IEnumerable<Result> GetResults()
                    {
     
                       //NOTE: Your JSON says there is a single department...
                       var dept = JsonConvert.DeserializeObject<Dept>(response.Content);
    
                    return dept.Result;
                    }
    
                foreach (var item in GetResults())
                    {
                    var Key = item.Key;
                    var Name = item.Name;
                    richTextBox5.AppendText(Key + " - " + Name + Environment.NewLine);
                    }


    but I got the same message

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[myprogram.Form1+Dept]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
    To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
    Path 'Result', line 1, position 10.


    if I use this code , is can get the induvial values 

                var res = JsonConvert.DeserializeObject<dynamic>(response.Content);
                var message = res.Message;
                var success = res.Success;
                var results = res.Result;
    ..etc
                richTextBox5.AppendText(" Message = " + message + Environment.NewLine);
                richTextBox5.AppendText(" Success = " + success + Environment.NewLine);
                richTextBox5.AppendText(" Results = " + results + Environment.NewLine);


    I understand I prob being really dumb here, but I cannot see how to get all the values,  in "Results" so I can utilize them.

    I'll keep trying though, and edit this reply if I find out

    would you be able to assist ? 

    UPDATE

    I can add the following code, to get all the data out if the JSON response, but I am not sure its correct for them querying the results nodes and querying 

                var res = JsonConvert.DeserializeObject<dynamic>(response.Content);
                var RID = res.RID;
                var clouddatetime = res.CloudDateTime;
                var message = res.Message;
                var success = res.Success;
    
                DataTable myTable;
                DataRow myNewRow;
                JObject result = JObject.Parse(response.Content);
    
                myTable = new DataTable("Results");
                myTable.Columns.Add("Key", typeof(string));
                myTable.Columns.Add("Name", typeof(string));
       
                foreach (var item in result["Result"])
                    {
                    myNewRow = myTable.NewRow();
                    myNewRow["Key"] = item["Key"].ToString(); //string
                    myNewRow["Name"] = item["Name"].ToString(); //string
    
                    myTable.Rows.Add(myNewRow);
                    }
    
                foreach (DataRow dr in myTable.Rows)
                    {
                    //richTextBox5.AppendText("Key: " + dr[0] + "\t Name : " + dr[1]+" \t");
                    }
    
                richTextBox5.AppendText("RID: " + RID + Environment.NewLine);
                richTextBox5.AppendText("CloudTimeDate: " + clouddatetime + Environment.NewLine);
                richTextBox5.AppendText("Success:" + success + Environment.NewLine);
                richTextBox5.AppendText("Message: " + message + Environment.NewLine);

    if (Name = "Bistro")
    {
    key = matching jey value
    }
    


    • Edited by G-Oker Sunday, July 5, 2020 11:11 AM addition code
    Sunday, July 5, 2020 9:15 AM
  • The code I posted does not line up with the error you're posting so it isn't the code I gave you.

    var dept = JsonConvert.DeserializeObject<Dept>(response.Content>();

    Notice the error message.

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[myprogram.Form1+Dept]'

    This is the same error you were getting before. The error says you're trying to read List<Dept> but the code I gave you is using `Dept`. The error clearly is not coming from that code. There are a couple of possibilities.

    1. There are compiler errors in your code but you have told the IDE to ignore the errors so since the code doesn't compile the debugger is running an older version of your code and hence producing the same runtime error. You need to fix the compiler errors and ultimately you should never agree to the prompts from the IDE to "run code anyway". 

    2. Your original code is still being executed and therefore producing the same error. The stack trace on the error will tell you exactly what line is producing the error so you can diagnose this quickly.

    I can verify that the code I gave you works correctly. I've taken the method I gave you put it into a simple console app that loads the JSON you posted from a file and prints out the result. I also took your original types that you gave. 

    using System;
    using System.Collections.Generic;
    using System.IO;
    
    using Newtonsoft.Json;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main ( string[] args )
            {
                var json = File.ReadAllText("test.json");
    
                var results = GetResults(json);
                foreach (var result in results)
                    Console.WriteLine($"{result.Key} = {result.Name}");
            }
    
            static IEnumerable<Result> GetResults ( string content )
            {   
                //NOTE: Your JSON says there is a single department...
                var dept = JsonConvert.DeserializeObject<Dept>(content);
    
                return dept.Result;
            }
        }
    
        public class Dept
        {
            public List<Result> Result { get; set; }
            public string RID { get; set; }
            public DateTime CloudDateTime { get; set; }
            public bool Success { get; set; }
            public string Message { get; set; }
        }
    
        public class Result
        {
            public string Key { get; set; }
            public string Name { get; set; }
        }
    }
    

    As discussed in the previous post your `Result` property needs to be a list to line up with the JSON so I made that change. However when you run the code you'll not get a valid result back. You likely haven't seen this problem yet because of the earlier error but as I mentioned you are not following standard conventions for properties and therefore the serializer cannot map your non-standard property names to the corresponding JSON fields. While you could annotate the types to get it to work or set up some defaults with the serializer, the more appropriate option is to follow the standard .NET casing conventions (Pascal). So I made that change to your types as well. With those 2 changes in place the JSON is properly read.

    Review your code for the issues I mentioned earlier and adjust your data types as I showed here and the JSON will load properly.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by G-Oker Friday, July 10, 2020 7:32 AM
    Sunday, July 5, 2020 6:48 PM
    Moderator