【问题标题】:Find a specific element anywhere in an arbitrary JSON在任意 JSON 中的任意位置查找特定元素
【发布时间】:2015-07-16 05:39:38
【问题描述】:

我是 JSON.NET 的新手,不知道该怎么做。

我有CartItem类,需要实现
GetAllCartItemsFromArbitraryJson(string jsonStr),如下:

class CartItem {
  public int Id;
  public int Qty;
}

List<CartItem> items = GetAllCartItemsFromArbitraryJson(jsonStr);

我只知道jsonStr 在某处包含一个或多个cartitems(我不知道有多深),例如。

{
  ... : {
    "cartitems": [{
        "id": "1",
        "qty": "1"
      },{
        "id": "2",
        "qty": "5"
      }
    ]
  },
  ... : {
    ... : {
      ...,
      "cartitems": [{
          "id": "10",
          "qty": "2"
        }
      ]
    }
  }
}

这个函数需要把所有的cartitems收集起来放到List&lt;CartItem&gt;里面

List<CartItem> GetAllCartItemsFromArbitraryJson(string jsonStr) {
  JObject json = JObject.Parse(jsonStr);
  // then what...?
}

所以List&lt;CartItem&gt; 将包含:

Id  Qty
1   1
2   5
10  2

你会如何在 C# 中做到这一点?

【问题讨论】:

  • 如果JObject.Parse(jsonStr) 成功,您可以通过json 对象访问它的属性。但是如果cartItems 被序列化为对象图的一部分,最方便的方法是反序列化整个图表,然后访问您想要的属性。
  • @YTAM:不,正如您在示例中看到的那样。 Amit:你是说我需要一个递归函数?我试过了,但我不明白如何循环 JToken 等
  • 使用SelectTokensToObject,像这样:var items = json.SelectTokens("..cartitems[*]").Select(t =&gt; t.ToObject&lt;CartItem&gt;()).ToList();
  • 布莱恩,感谢您的“重复”,但它完全不同。我的问题的答案只有一行(dbc 很接近但不起作用)。如果可以重新打开,我会发布它。

标签: c# json json.net


【解决方案1】:

这是一个有效的解决方案:

List<CartItem> GetAllCartItemsFromArbitraryJson(string jsonStr) {
  JObject json = JObject.Parse(jsonStr);

  return json.Descendants().OfType<JProperty>()  // so we can filter by p.Name below
             .Where(p => p.Name == "cartitems")
             .SelectMany(p => p.Value)           // selecting the combined array (joined into a single array)
             .Select(item => new CartItem {
                 Id  = (int)item["id"],
                 Qty = (int)item["qty"]
             }).ToList();
}

希望它对某人有所帮助。
不过,我是 JSON 新手,是通过反复试验得到的。所以让我知道它是否可以改进:)

【讨论】:

    【解决方案2】:

    解析为动态并遍历项目。

    public List<CartItem> PostAllCartItemsFromArbitraryJson(string jsonStr)
    {
        List<CartItem> AllCartItems = new List<CartItem>();
        try
        {
            dynamic BaseJson = JObject.Parse(jsonStr.ToLower());
    
            CheckForCarts(AllCartItems, BaseJson);
        }
        catch (Exception Error)
        {
        }
    
        return AllCartItems;
    }
    
    private void CheckForCarts(List<CartItem> AllCartItems, dynamic BaseJson)
    {
        foreach (dynamic InnerJson in BaseJson)
        {
            if (InnerJson.Name == "cartitems")
            {//Assuming this is an [] of cart items
                foreach (dynamic NextCart in InnerJson.Value)
                {
                    try
                    {
                        CartItem FoundCart = new CartItem();
                        FoundCart.Id = NextCart.id;
                        FoundCart.Qty = NextCart.qty;
                        AllCartItems.Add(FoundCart);
                    }
                    catch (Exception Error)
                    {
                    }
                }
            }
            else if (InnerJson.Value is JObject)
            {
                CheckForCarts(AllCartItems, InnerJson.Value);
            }
        }
    }
    
    public class CartItem
    {
        public int Id;
        public int Qty;
    }
    

    对于您的示例输入,这会生成:

    [{"Id":1,"Qty":1},{"Id":2,"Qty":5},{"Id":10,"Qty":2}]

    【讨论】:

    • +1 谢谢布赖恩!它适用于示例 JSON。但它不适用于某些真正的 JSON,因为“cartitems”也可能在 JArray 中(您的代码只检查 JObject)。无论如何,我找到了一个更简单的 LINQ 解决方案(到目前为止)。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2015-01-10
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多