从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:StartArray。小路

Posted

技术标签:

【中文标题】从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:StartArray。小路【英文标题】:Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path 【发布时间】:2016-04-13 22:26:11 【问题描述】:

我正在开发一个涉及位置的 Windows Phone 8.1 应用程序。我从我的 API 接收 Json 数据。我的 API 返回的数据如下所示:

[
    "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"
]

我正在反序列化我的 Json 数据并将其放入名为 LocationData 的类中。当我运行我的代码时,它给了我一个错误:

从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:StartArray。路径

我哪里错了?这是我的代码:

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);
        
    

我也尝试使用 JArray。我的代码如下:

 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);
        
    

这也给了我一个错误:

无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'MMI_SpeechRecog.Model.LocationData',因为该类型需要 JSON 对象(例如 "name":"value")才能正确反序列化。

【问题讨论】:

【参考方案1】:

您问题的第一部分与Why do I get a JsonReaderException with this code? 重复,但与该(我的)答案最相关的部分是:

[A] JObject 不是 JSON.net 中所有内容的基本基本类型,但 JToken 是。所以即使你可以说,

object i = new int[0];

在 C# 中,你不能说,

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

在 JSON.net 中。

您想要的是JArray.Parse,它将接受您传递给它的数组(在您的API 响应中由开头的[ 表示)。这就是错误消息中的“StartArray”告诉您的内容。

至于你使用JArray时发生了什么,你使用的是arr而不是obj

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

交换它,我相信它应该可以工作。

虽然我很想将arr 直接反序列化为IEnumerable&lt;LocationData&gt;,这样可以节省一些代码和循环遍历数组的工作量。如果不打算单独使用解析后的版本,最好避免使用。

【讨论】:

感谢您的回答。我将单独使用解析后的数据。在这种情况下,它以 4 个搜索匹配响应我。我需要单独显示它们,然后根据用户的偏好为每个执行背景。 如果你想支持所有情况,我认为你应该使用 JToken,在这里查看他们的源代码:jsonschemavalidator.net【参考方案2】:

在这种情况下,您知道数组中的所有项都位于首位,您可以将字符串解析为 JArray,然后使用 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());

【讨论】:

没有理由再次重新序列化和解析嵌套的 JSON 对象。如果您希望数组中的项目作为对象,请执行var jsonObjects = jsonArray.OfType&lt;JObject&gt;().ToList(); 工作...!感谢@dbc 您的代码“var jsonObjects = jsonArray.OfType().ToList();”为我工作。 JsonArray => 列表【参考方案3】:

我的 Xamarin Windows Phone 8.1 应用程序遇到了一个非常相似的问题。 JObject.Parse(json) 对我不起作用的原因是因为我的 Json 有一个开头“[”和一个结尾“]”。为了使它工作,我不得不删除这两个字符。从您的示例来看,您可能遇到了同样的问题。

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

然后我就可以使用 JObject.Parse(jsonResult) 并且一切正常。

【讨论】:

感谢您的帮助。虽然这些只是我放在我的文本文件中。我应该删除它们。 加 1 = 当您也使用 webclient 和 JObject 调用 api 时的良好解决方案。 谷歌把我带到了这里,当我在调试时,我看到了开始和结束的括号,被删除了,一切都很好。谢谢! 很棒的帖子。谢谢!

以上是关于从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:StartArray。小路的主要内容,如果未能解决你的问题,请参考以下文章

如何在不知道 json 键的情况下使用 JsonReader 从 json 读取值

使用 JsonReader 将缓存的 Json 文件读取为 ByteArray

JsonReader - 读取数组抛出预期名称但为 NULL

使用 JsonReader 读取动态 json 文件

c# JsonReader读取json字符串

GitHub Actions 因从 JsonReader 错误读取 JToken 而失败