0

I tried to print all of the sub keys in "items" from json file(shown below), but getting an invalid cast exception on this line:

foreach (KeyValuePair<string, JToken> sub in (JObject)obj2["items"])

I have no idea why it keeps showing this error.

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;


public class JsonReader : MonoBehaviour
{
    [SerializeField]
    public string filePath;

    [ContextMenu("Load Data")]
    private void LoadData()
    {
        JObject obj2 = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(filePath));
        foreach (KeyValuePair<string, JToken> sub in (JObject)obj2["items"])
        {

            Debug.Log(sub.Key);
        }
    }   
}

JSON File Content

{
    "items": [
        {
            "id": "143675",
            "item": "Action Figure",
            "name": "Goku",
            "color": "Orange"
        },
        {
            "id": "258943",
            "item": "Water Bottle",
            "name": "Pcares",
            "color": "Silver"
        },
        {
            "id": "326824",
            "item": "White Board",
            "name": "Boardy",
            "color": "White"
        },
        {
            "id": "423168",
            "item": "Monitor",
            "name": "Dell",
            "color": "Black"
        }
    ]
}

I want the expected output to show all of the keys so like:

id
item
name
color

Any help would be appreciated!

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I'd say that obj2["items"] is a JArray, so it cannot be cast to a JObject? and you would need a foreach(JObject object in (Jarray)obj2["items"]) first followed by looping through the keys? [this might help](https://stackoverflow.com/questions/16045569/how-to-access-elements-of-a-jarray) – Arno May 02 '19 at 06:48

4 Answers4

4

If you look closely, the value under the key items is an array:

"items": [ // <--- square bracket!
    {
        "id": "143675",
        "item": "Action Figure",
        "name": "Goku",
        "color": "Orange"
    },

The keys you want to get are in the elements in the array. Assuming that there will always be items in the array, you can do:

foreach (KeyValuePair<string, JToken> sub in (JObject)obj2["items"][0]) 

Notice the [0] at the end. This gets the first item of the array.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

The generic type of JsonConvert.DeserializeObject should be your domain class type to map the properties.

Example:

  public class MyItem
  {
       public int Id { get; set; }
       public string Item { get; set; }
  }

But be careful: property names and json names case sensitive should be equal

programmer444
  • 156
  • 1
  • 5
  • 1
    That doesn't answer why the current code fails though. While it's often useful to create a domain class, it's not *required*. – Jon Skeet May 02 '19 at 06:49
0

You are using KeyValuePair<string, JToken> in foreach

But beware that KeyValuePair is used while deserializing JSON when your JSON have key : value pair like

{
  "ABC" : {
      "X" : "x",
      "Y" : "y",
      "Z" : "z"
  }
}

In above json ABC is a Key in KeyValuePair and whole object associated to ABC is an Value of ABC key.

But

Your json slightly different than above, means you have an array of objects associated with items key

And you are using (JObject)obj2["items"] that means you are iterate over items array but inside items array there is no key/value pair exist, only objects have

So far you need to use something like below,

foreach (JObject jObject in (JArray)obj2["items"])
{
    Debug.Log(jObject["id"].ToString());
    Debug.Log(jObject["item"].ToString());
    Debug.Log(jObject["name"].ToString());
    Debug.Log(jObject["color"].ToString());
}

By this way you can retrieve all the objects inside your items array

er-sho
  • 9,581
  • 2
  • 13
  • 26
0

You have written foreach (KeyValuePair<string, JToken> sub in (JObject)obj2["items"])

here obj2["items"] is of JArray type and not JObject

The invalidCastException is because you are trying to cast a JArray type of object to JObject in the foreach statement.

Going by what you want to achieve ultimately, it seems that you have written everything correctly but missed to add [0] at the end of (JObject)obj2["items"]

So the correct foreach statement would be:

foreach (KeyValuePair<string, JToken> sub in (JObject)obj2["items"][0]) // you missed to add this [0] in your code

akg179
  • 1,287
  • 1
  • 6
  • 14