【问题标题】:C# InvalidCastException: Specified cast is not valid for JSON.NetC# InvalidCastException:指定的强制转换对 JSON.Net 无效
【发布时间】:2019-05-02 06:42:26
【问题描述】:

我试图从 json 文件(如下所示)中打印“items”中的所有子键,但在这一行得到一个无效的强制转换异常:

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

我不知道为什么它一直显示这个错误。

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 文件内容

{
    "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"
        }
    ]
}

我希望预期的输出显示所有键,例如:

id
item
name
color

任何帮助将不胜感激!

【问题讨论】:

  • 我会说 obj2["items"] 是一个 JArray,所以它不能转换为 JObject?你需要一个 foreach(JObject object in (Jarray)obj2["items"]) 首先然后遍历键? this might help

标签: c# json unity3d json.net


【解决方案1】:

如果仔细看,items 键下的值是一个数组:

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

您要获取的键在数组中的元素中。假设数组中总会有项目,你可以这样做:

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

注意最后的[0]。这将获取数组的第一项。

【讨论】:

    【解决方案2】:

    JsonConvert.DeserializeObject 的泛型类型应该是您的域类类型来映射属性。

    例子:

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

    但要注意:属性名和json名区分大小写应该相等

    【讨论】:

    • 这并不能解释为什么当前代码会失败。虽然创建域类通常很有用,但它不是必需
    【解决方案3】:

    您在foreach 中使用KeyValuePair&lt;string, JToken&gt;

    但请注意,当您的 JSON 具有 key : value 对像时,在反序列化 JSON 时会使用 KeyValuePair

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

    在上面的 json 中,ABCKeyKeyValuePair 中,与 ABC 关联的整个对象是 ValueABC 键。

    但是

    您的 json 与上面略有不同,这意味着您有一个与 items 键关联的对象数组

    而您正在使用(JObject)obj2["items"],这意味着您正在迭代items 数组,但在items 数组中不存在键/值对,只有对象有

    到目前为止,您需要使用以下内容,

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

    通过这种方式,您可以检索 items 数组中的所有对象

    【讨论】:

      【解决方案4】:

      你写了foreach (KeyValuePair&lt;string, JToken&gt; sub in (JObject)obj2["items"])

      这里obj2["items"]JArray 类型而不是JObject

      invalidCastException 是因为您试图在 foreach 语句中将 JArray 类型的对象强制转换为 JObject

      按照您最终想要实现的目标,您似乎已经正确编写了所有内容,但错过了在(JObject)obj2["items"]末尾添加[0]

      所以正确的foreach 语句应该是:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-12
        • 1970-01-01
        • 2014-05-09
        • 1970-01-01
        • 2019-11-02
        • 2011-01-28
        • 2015-01-06
        • 1970-01-01
        相关资源
        最近更新 更多