简体   繁体   中英

Extract properties from Newtonsoft jObject

I have a .net core console application where I am trying to get the values of two properties that are within a returned JSON object. I have highlighted where the error is on line 43, can someone please show me where I am going wrong thank you!

Error:

System.ArgumentException: Accessed JArray values with invalid key value: "name". Int32 array index expected.

at Newtonsoft.Json.Linq.JArray.get_Item(Object key)
at PBXApp.Program.GetUser() in C:\Development\PBXApp\PBXApp\Program.cs:line 43

Returned JSON:

{ 
   "results":[ 
      { 
         "name":"bulbasaur",
         "url":"https://pokeapi.co/api/v2/pokemon/1/"
      },
      { 
         "name":"ivysaur",
         "url":"https://pokeapi.co/api/v2/pokemon/2/"
      },
      { 
         "name":"venusaur",
         "url":"https://pokeapi.co/api/v2/pokemon/3/"
      }
   ]
}

Program.cs -

// retrieve asynchronous data from remote api
    public static async Task GetUser()
    {
        //baseUrl
        string baseUrl = "http://pokeapi.co/api/v2/pokemon/";
        try
        {
            // HttpClient implements a IDisposable interface
            using (HttpClient client = new HttpClient())
            {
                //initiate Get Request (await will execute the using statement in order)
                using (HttpResponseMessage res = await client.GetAsync(baseUrl))
                {
                    //get content from response, then convert it to a c# object
                    using (HttpContent content = res.Content)
                    {
                        //assign content to data variable by converting into a string using await
                        var data = await content.ReadAsStringAsync();
                        //convert data using newtonsoft JObject Parse class method
                        if (data != null)
                        {
                            //parse data into an object.
                            var dataObj = JObject.Parse(data)["results"];
enter code here
                            //ERROR ON THIS LINE
                            UserItem userItem = new UserItem(name: $"{dataObj["name"]}", url: $"{dataObj["url"]}");

                            //log userItem name and url to console
                            Console.WriteLine("Name:{0} Url:{1}", userItem.Name, userItem.Url);
                        }
                        else
                        {
                            Console.WriteLine("No returned data");
                        }
                    }
                }
            }
        }
        //exceptions
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
    }

UserItem.cs -

public class UserItem
    {
        public UserItem(string name, string url)
        {
            Name = name;
            Url = url;
        }
        public string Name { get; set; }
        public string Url { get; set; }
    }

dataObj is a JSON array, but not with named keys. It is just a regular array. So you can't access it with a key named "name", because that key doesn't exist.

You could use a numeric index, but you don't know in advance (from the JObject) how long the array is. So it's better to parse it as an array, and loop over the items:

var dataObj = JArray.Parse(data)["results"];
foreach (var record in dataObj)
{
    var name = record["name"];
    // ...
}

But why go through all the hassle of manually parsing JSON? Just create classes to hold the results, and deserialize all at once:

public class Pokémon
{
    public string name { get; set; }
    public string url { get; set; }
}

public class ListOfPokémon
{
    public List<Pokémon> results { get; set; }
}

var result = JsonConvert.DeserializeObject<ListOfPokémon>(jsonString);
foreach (var p in result.results)
{
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM