Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path
Asked Answered
S

6

104

I am working on a Windows Phone 8.1 application involving location. I am receiving Json data from my API. My API returns data that looks like:

[{
    "country": "India",
    "city": "Mall Road, Gurgaon",
    "area": "Haryana",
    "PLZ": "122002",
    "street": "",
    "house_no": "",
    "POI": "",
    "type": "17",
    "phone": "",
    "lng": 77.08972334861755,
    "lat": 28.47930118040612,
    "formatted_address": "Mall Road, Gurgaon 122002, Haryana, India"
},
{
    "country": "India",
    "city": "Mall Road, Kanpur",
    "area": "Uttar Pradesh",
    "PLZ": "208004",
    "street": "",
    "house_no": "",
    "POI": "",
    "type": "17",
    "phone": "",
    "lng": 80.35783410072327,
    "lat": 26.46026740300029,
    "formatted_address": "Mall Road, Kanpur 208004, Uttar Pradesh, India"
},
{
    "country": "India",
    "city": "Mall Road Area, Amritsar",
    "area": "Punjab",
    "PLZ": "143001",
    "street": "",
    "house_no": "",
    "POI": "",
    "type": "17",
    "phone": "",
    "lng": 74.87286686897278,
    "lat": 31.64115178002094,
    "formatted_address": "Mall Road Area, Amritsar 143001, Punjab, India"
},
{
    "country": "India",
    "city": "Vasant Kunj (Mall Road Kishan Garh), New Delhi",
    "area": "Delhi",
    "PLZ": "110070",
    "street": "",
    "house_no": "",
    "POI": "",
    "type": "18",
    "phone": "",
    "lng": 77.1434211730957,
    "lat": 28.51363217008815,
    "formatted_address": "Vasant Kunj (Mall Road Kishan Garh), New Delhi 110070, Delhi, India"
}]

I am deserializing my Json data and putting it into a class named LocationData. When I run my code, it gives me an error:

Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path

Where am I going wrong? Here is my code:

private async void GetAPIData()
    {
        string _serviceUrl = "https://api.myweblinkapiprovider/v2&q=" + UserRequestedLocation;
        HttpClient client = new HttpClient();

        HttpResponseMessage responce = await client.GetAsync(new Uri(_serviceUrl));

        if (responce.Content != null)
        {
            var respArray = JObject.Parse(await responce.Content.ReadAsStringAsync());
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.NullValueHandling = NullValueHandling.Ignore;
            settings.MissingMemberHandling = MissingMemberHandling.Ignore;
            var rcvdData = JsonConvert.DeserializeObject<LocationData>(respArray.ToString(), settings);
            UpdateMapData(rcvdData);
            UpdateTextData(rcvdData);
        }
    }

I also tried to use a JArray. My code is as below:

 private async void GetAPIData()
    {
        string _serviceUrl = "https://api.myweblinkprovider.com/v3?fun=geocode&lic_key=MyKey" + UserRequestedLocation;
        HttpClient client = new HttpClient();

        HttpResponseMessage responce = await client.GetAsync(new Uri(_serviceUrl));

        JArray arr = JArray.Parse(await responce.Content.ReadAsStringAsync());

        foreach (JObject obj in arr.Children<JObject>())
        {
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.NullValueHandling = NullValueHandling.Ignore;
            settings.MissingMemberHandling = MissingMemberHandling.Ignore;
            var rcvdData = JsonConvert.DeserializeObject<LocationData>(arr.ToString(), settings);
            UpdateMapData(rcvdData);
            UpdateTextData(rcvdData);
        }
    }

It also gives me an error:

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

Swint answered 9/1, 2016 at 6:45 Comment(0)
S
135

The first part of your question is a duplicate of Why do I get a JsonReaderException with this code?, but the most relevant part from that (my) answer is this:

[A] JObject isn't the elementary base type of everything in JSON.net, but JToken is. So even though you could say,

object i = new int[0];

in C#, you can't say,

JObject i = JObject.Parse("[0, 0, 0]");

in JSON.net.

What you want is JArray.Parse, which will accept the array you're passing it (denoted by the opening [ in your API response). This is what the "StartArray" in the error message is telling you.

As for what happened when you used JArray, you're using arr instead of obj:

var rcvdData = JsonConvert.DeserializeObject<LocationData>(arr /* <-- Here */.ToString(), settings);

Swap that, and I believe it should work.

Although I'd be tempted to deserialize arr directly as an IEnumerable<LocationData>, which would save some code and effort of looping through the array. If you aren't going to use the parsed version separately, it's best to avoid it.

Sullage answered 9/1, 2016 at 7:9 Comment(2)
thanks for the answer. I'll be using the parsed data separately. In this case it responded to my with 4 search matches. I need to display them individually and then carry out the background for each based on user's preference.Swint
I think you should use JToken if you want to support all cases, see their source code here: jsonschemavalidator.netDocker
A
61

In this case that you know that you have all items in the first place on array you can parse the string to JArray and then parse the first item using JObject.Parse

var  jsonArrayString = @"
[
  {
    ""country"": ""India"",
    ""city"": ""Mall Road, Gurgaon"",
  },
  {
    ""country"": ""India"",
    ""city"": ""Mall Road, Kanpur"",
  }
]";
JArray jsonArray = JArray.Parse(jsonArrayString);
dynamic data = JObject.Parse(jsonArray[0].ToString());
Abscond answered 15/10, 2017 at 10:56 Comment(2)
There is no reason to re-serialize and parse the nested JSON object a second time. If you want the items in the array as objects, do var jsonObjects = jsonArray.OfType<JObject>().ToList();Prefatory
WORKED...! Thanks @Prefatory your code "var jsonObjects = jsonArray.OfType<JObject>().ToList();" worked for me. JsonArray => ListNellienellir
A
23

I ran into a very similar problem with my Xamarin Windows Phone 8.1 app. The reason JObject.Parse(json) would not work for me was because my Json had a beginning "[" and an ending "]". In order to make it work, I had to remove those two characters. From your example, it looks like you might have the same issue.

jsonResult = jsonResult.TrimStart(new char[] { '[' }).TrimEnd(new char[] { ']' });

I was then able to use the JObject.Parse(jsonResult) and everything worked.

Alban answered 12/4, 2017 at 13:31 Comment(4)
Thanks for the assist. Although those were just put by me in my text file. I should have removed them.Swint
plus 1 = good solution for when you call api using webclient and JObject too.Yeargain
Google brought me here and when I was in debug I saw the beginning and ending brackets, removed and all is well. Thanks!Wiburg
great post. Thanks!Heydon
S
1

The following worked for me to convert a list of objects to json.

    using Newtonsoft.Json;
    static void  Main(string[] args)
    {
        List<eventResponse> o = new List<eventResponse>() 
        {
            new eventResponse { acknowledge = "test" } ,
            new eventResponse { acknowledge = "test 2" }
        };

        var json = JsonConvert.SerializeObject(o);
        JArray jo = JArray.Parse(json); 
        Console.WriteLine(jo);
}

public class eventResponse
{
    public string acknowledge { get; set; }
}
Scopas answered 13/5, 2022 at 12:15 Comment(0)
M
0

A delayed answer but if you have access to the API you can work on the javascript object to make it as JSon. Something like

var  jsonAddresses = { "addresses":
[
  {
    "country": "India",
    "city": "Mall Road, Gurgaon",
  },
  {
    "country": "India",
    "city": "Mall Road, Kanpur",
  }
]};

Then in C#

JObject Addjson = JObject.Parse(model.YourAddressesSampleJSONStr);
Maximamaximal answered 5/4, 2022 at 18:11 Comment(0)
D
0

Just FYI - you can try the more generic JToken.Parse(string). This will accept both an array and an object. Then you can use JToken is JArray to act on it accordingly.

Example:

var jsonString = "[{\"key\" : \"value\"}]";
var jtoken = JToken.Parse(jsonString);
if (jtoken is JArray jArray)
  Console.WriteLine(jArray); //Do something with jArray
else
  Console.WriteLine(jtoken); //Do something with jtoken (or convert to jobject)
Dateless answered 10/12, 2023 at 7:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.