1

I have JSON file like:

[
  12,
  [
    {
      "id": "131",
      "name": "Cate"
    },
        {
      "id": "132",
      "name": "Mike"
    }
  ],
  "Result OK"
]

And Code:

        private static void Main(string[] args)
        {
                using (var r = new StreamReader(@"C:\Path\data1.json"))
                {
                    var json = r.ReadToEnd();
                    try
                    {
                        var items = JsonConvert.DeserializeObject<JsonBody>(json);
                        Console.WriteLine(items);
                    }
                    catch (JsonSerializationException ex)
                    {
                        Console.WriteLine(ex);
                    }
                }
        }
        public class JsonBody
        {
            public int someint;
            public List<Dictionary<string, Item>> item;
            public string somestring;

        }
        public class Item
        {
            [JsonProperty("id")] public string id;
            [JsonProperty("name")] public string name;
        }

Error:Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Json_parser.Parse2+JsonBody' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

What should be rewritten in the code to avoid this error. How do I parse this JSON correctly? I need to get all items from the Item class.

  • 2
    The root object of this json is an array, containing 3 elements, the number 12, a nested array, and the string "Result OK". You need to deserialize this into an array of object or similar in order to handle it. – Lasse V. Karlsen Dec 20 '19 at 08:58
  • @JohnathanBarclay I get this json from a website – Cate Borisova Dec 20 '19 at 09:01
  • https://stackoverflow.com/q/8030538/1271037 – dovid Dec 20 '19 at 09:01
  • 1
    @JohnathanBarclay Sure it can. Even this is valid json: `"Result OK"`, it's just a string, but it is valid JSON. – Lasse V. Karlsen Dec 20 '19 at 09:01
  • 1
    Try this: `JToken root = JToken.Parse(json); var items = root[1].ToObject();` You probably need more error checking though. – Lasse V. Karlsen Dec 20 '19 at 09:02
  • 1
    @LasseV.Karlsen my mistake. – Johnathan Barclay Dec 20 '19 at 09:04
  • @CateBorisova the JsonBody class looks nothing like the JSON contents. You have an array of mixed types, (number, array, string). The second element looks like an array of Items – Panagiotis Kanavos Dec 20 '19 at 09:05
  • As far as I know, there is no way to create a strong type for the root of this json document to deserialize into, you need one of the "generic ways" in Json.Net to handle untyped data, and when you know you have the array you can convert it into a strong type. I could be wrong though. – Lasse V. Karlsen Dec 20 '19 at 09:05
  • If you know 100% that this will always be an array, you can do `JArray root = JArray.Parse(json);`. If you know 100% the items nested array will be the 2nd element of the root array, you can do `var items = root[1].ToObject();`. If you need to hunt for the array, loop through the root and look for nested `JArray` elements. – Lasse V. Karlsen Dec 20 '19 at 09:07

2 Answers2

1

Since the root of your JSON document is a list, you need to deserialize it into a collection type in C# using Json.Net. Unfortunately, this kind of data structure with mixed element types is a bit hard to consume.

If you know 100% that the root of the document will always be an array, you can deserialize it like this:

JArray root = JArray.Parse(json);

Then, if you know 100% that the 2nd element of this array will be the nested array of items you're interested in you can use this:

Item[] items = root[1].ToObject<Item[]>();

So your method could be simplified to:

string json = File.ReadAllText(@"C:\Path\data1.json");
JArray root = JArray.Parse(json);
Item[] items = root[1].ToObject<Item[]>();

However, if you need to hunt for the nested array, in that it will not always be the 2nd element, you can use this:

string json = File.ReadAllText(@"C:\Path\data1.json");
JArray root = JArray.Parse(json);
foreach (var element in root)
    if (element is JArray)
    {
        Item[] items = element.ToObject<Item[]>();
        // ...
    }
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
0

At first sight the problem come from the model we are using for the deserialization.

Try this one instead, in which the dictionary is replace by just your model Item :

        public class JsonBody
        {
            public int someint;
            public List<Item> item;
            public string somestring;

        }

As mentionned by @Lasse V. Karlsen it need to be deserialized into a list of JsonBody, so you have to alter this line of code as well:

var items = JsonConvert.DeserializeObject<List<JsonBody>>(json);
Ragou
  • 1
  • 4