使用 Newtonsoft.JSON 解析动态 JSON 在反序列化对象中缺少数组

Parsing dynamic JSON with Newtonsoft.JSON is missing array in the deserialized object

当我到达第三个循环时,它爆炸了,因为它找不到 table 上的 "Row"。为什么?

var converter = new ExpandoObjectConverter();
dynamic deserializeObject = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);

foreach (var model in deserializeObject.Model)
{
    foreach (var table in model.Table)
    {
        foreach (var row in table.Row)
        {
            Console.WriteLine(row.BookId + ": " + row.BookName);
        }
    }
}

JSON:

{
  "Model": [
    {
      "Field1": "Field1Value",
      "Field2": "Field2Value",
      "Field3": "Field3Value",
      "Table": {
        "Row": [
          {
            "BookId": "1",
            "BookName": "Computer Architecture",
            "Category": "Computers",
            "Price": "125.60"
          },
          {
            "BookId": "2",
            "BookName": "Asp.Net 4 Blue Book",
            "Category": "Programming",
            "Price": "56.00"
          },
          {
            "BookId": "3",
            "BookName": "Popular Science",
            "Category": "Science",
            "Price": "210.40"
          },
          {
            "BookId": "4",
            "BookName": "Mission Impossible",
            "Category": "Adventure",
            "Price": "210.40"
          }
        ]
      }
    },
    {
      "ClientFirstName": "Jane",
      "ClientLastName": "Doe",
      "Table": [
        {
          "Row": [
            {
              "BookId": "1",
              "BookName": "Computer Architecture",
              "Category": "Computers",
              "Price": "125.60"
            },
            {
              "BookId": "3",
              "BookName": "Popular Science",
              "Category": "Science",
              "Price": "210.40"
            },
            {
              "BookId": "4",
              "BookName": "Mission Impossible",
              "Category": "Adventure",
              "Price": "210.40"
            }
          ]
        },
        {
          "Row": [
            {
              "BookId": "1",
              "BookName": "Computer Architecture",
              "Category": "Computers",
              "Price": "125.60"
            },
            {
              "BookId": "4",
              "BookName": "Mission Impossible",
              "Category": "Adventure",
              "Price": "210.40"
            }
          ]
        }
      ]
    }
  ]
}

问题不在于您反序列化对象的方式。您的 json 与包含 table 的两个对象不同。

第一个对象是一个 table,它有一个行数组:

    "Table": {
    "Row": [
      {
        "BookId": "1",
        "BookName": "Computer Architecture",
        "Category": "Computers",
        "Price": "125.60"
      },
      {
        "BookId": "2",
        "BookName": "Asp.Net 4 Blue Book",
        "Category": "Programming",
        "Price": "56.00"
      },
      {
        "BookId": "3",
        "BookName": "Popular Science",
        "Category": "Science",
        "Price": "210.40"
      },
      {
        "BookId": "4",
        "BookName": "Mission Impossible",
        "Category": "Adventure",
        "Price": "210.40"
      }
    ]
  }
}

你的第二个客户端对象有一个数组的数组。此外,在 table 数组之外的客户端对象中还有第二个行数组。

       "Table": [
    {
      "Row": [
        {
          "BookId": "1",
          "BookName": "Computer Architecture",
          "Category": "Computers",
          "Price": "125.60"
        },
        {
          "BookId": "3",
          "BookName": "Popular Science",
          "Category": "Science",
          "Price": "210.40"
        },
        {
          "BookId": "4",
          "BookName": "Mission Impossible",
          "Category": "Adventure",
          "Price": "210.40"
        }
      ]
    },
    {
      "Row": [
        {
          "BookId": "1",
          "BookName": "Computer Architecture",
          "Category": "Computers",
          "Price": "125.60"
        },
        {
          "BookId": "4",
          "BookName": "Mission Impossible",
          "Category": "Adventure",
          "Price": "210.40"
        }
      ]
    }

我建议要么以不同的方式格式化您的 json,要么创建一种不同的方法来遍历您在 json 中拥有的两种类型的 table。一个是对象,一个是数组。

例如。我将您的动态更改为 Newtonsoft.Json.Linq 中的 Newtonsoft Jobject;这将在两个 table 上出现,一个是对象,第二个是数组。

       var converter = new ExpandoObjectConverter();
        var deserializeObject = JsonConvert.DeserializeObject<JObject>(jsonString, converter);

        foreach(var v in deserializeObject["Model"])
        {
            if(v["Table"] != null && v["Table"].Type == JTokenType.Object)
            {
                foreach (var x in v["Table"]["Row"])
                {
                    Console.Write(x["BookId"] + " : " + x["BookName"] + Environment.NewLine);
                }
            }
            else if (v["Table"].Type == JTokenType.Array)
            {
                foreach(var subTable in v["Table"])
                {
                    foreach (var row in subTable["Row"])
                    {
                        Console.Write(row["BookId"] + " : " + row["BookName"] + Environment.NewLine);
                    }
                }

            }              
        }
您的 JSON 中的

Table 属性 在一个实例中被格式化为数组,在另一个实例中被格式化为对象。前者反序列化为List<object>,后者反序列化为KeyValuePair<string, object>

您可以检查当前实例中的 Table 是否为 KeyValuePair<string, object> 类型,然后相应地进行:

foreach (var model in deserializeObject.Model)
{
    foreach (var table in model.Table)
    {
        if(table is KeyValuePair<string, object>)
        {
            foreach (var row in table.Value)
            {
                Console.WriteLine(row.BookId + ": " + row.BookName);
            }
        }
        else
        {
            foreach (var row in table.Row)
            {
                Console.WriteLine(row.BookId + ": " + row.BookName);
            }
        }
    }
}

dotnetfiddle demo