【问题标题】:Deserialize only one property of a JSON file仅反序列化 JSON 文件的一个属性
【发布时间】:2017-06-22 14:00:20
【问题描述】:

我遇到了一个问题。 我想反序列化来自服务器的复杂 JSON 响应,但我只需要它的一部分。

这是一个例子:

{
 "menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
 }
}

我也使用了Csharp2json来获取我需要的类对象,我只是根据我的需要修改了菜单类:

    public class Menuitem
{
    public string value { get; set; }
    public string onclick { get; set; }
}

public class Popup
{
    public IList<Menuitem> menuitem { get; set; }
}

public class Menu
{
    public Popup popup { get; set; }
}

public class RootObjectJourney
{
    public Menu menu { get; set; }
}

现在,如果我只需要弹出值和他的孩子,我该如何反序列化?

【问题讨论】:

  • 你为什么不把所有的响应都隐藏起来,只选择弹出窗口?对所有响应进行去现实化只是比您的情况所需的成本略高
  • 你所拥有的应该已经做你所描述的。当你通过反序列化器运行它时会发生什么?即var root = JsonConvert.DeserializeObject&lt;RootObjectJourney&gt;(json); var menuitems = root.menu.popup.menuitem; ?
  • 在这种情况下,我会反序列化所有的东西。但这只是我实际 Json 的简化。在这个 url 上执行 Get 请求以获取实际的 json:transport.opendata.ch/v1/… 它非常复杂且冗长。 @MarcGravell 它说“对象引用未设置为对象的实例。”
  • @A.Silva 那么您的缩减模型与实际数据不匹配;我不能告诉你在哪里,因为你链接的 JSON 与你提供的模型无关
  • @MarcGravell,也许我没有理解 100% 的错误。

标签: c# json visual-studio json.net


【解决方案1】:

您实际上可以利用 NewtonSoft.Json 的 Linq 命名空间并稍微修改您的代码以仅从 JSON 中获取“弹出”元素。

你的班级结构保持不变。确保使用命名空间

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

然后在你的代码中,一旦你有了 JSON 字符串,你就可以使用“JObject”静态方法“Parse”来解析 JSON,比如

   var parsedObject = JObject.Parse(jsonString);

这将为您提供 JObject,您可以使用它访问所有 J​​SON 键,就像字典一样。

var popupJson = parsedObject["menu"]["popup"].ToString();

这个 popupJson 现在只有弹出键的 JSON。 有了这个,您可以使用 JsonConvert 来反序列化 JSON。

var popupObj = JsonConvert.DeserializeObject<Popup>(popupJson);

这个 popupObj 只有菜单项列表。

【讨论】:

  • 呃,从字符串到 json-object 到字符串到 Popup 对象的往返。这可能比只吃一大堆更贵。
  • 您想要从 JObject 转换为自定义类的操作如下:stackoverflow.com/a/12208692/736079
【解决方案2】:

如果打算只反序列化一个属性,由于其灵活性,我通常更喜欢使用 JsonPath。请检查下面的代码

var jsonQueryString = "{ 'firstName': 'John',
 'lastName' : 'doe',
 'age'      : 26,}";
JObject o = JObject.Parse(jsonQueryString);
JToken token= o.SelectToken("$.age");   
Console.WriteLine(token);

如果你的 Json 很复杂,你可以使用 JsonPath 的强大功能。 您可以查看https://support.smartbear.com/readyapi/docs/testing/jsonpath-reference.html#examples 获取 JsonPath 详细文档和示例。

我还包括以下示例以获取更多使用信息:

JObject o = JObject.Parse(@"{
        'store': {
            'book': [
            {
                'category': 'history',
                'author': 'Arnold Joseph Toynbee',
                'title': 'A Study of History',
                'price': 5.50
            },
            ...
            ]
        },
        'expensive': 10
        }");
        //gets first book object
        Console.WriteLine(o.SelectToken("$..book[0]"));
        //get first book's title
        Console.WriteLine(o.SelectToken("$..book[0].title"));

        // get authors of the books where the books are cheaper then 10 $
        foreach (var token in o.SelectTokens("$..[?(@.price < 10)].author"))
            Console.WriteLine(token);

【讨论】:

    【解决方案3】:

    如果你不使用Newtonsoft,而在.NET Core中使用System.Text.Json,你可以使用这个:

    var post = JsonDocument.Parse(stringifiedJson);
    var cat = post.RootElement.GetProperty("category").GetString();
    

    您在这里看到GetString 将值转换为字符串,还有其他重载可用于将json 值转换为Int32 等。

    【讨论】:

      【解决方案4】:

      .NET 5+

      解决方法很简单:

      using System.Text.Json;
      
      var doc = JsonDocument.Parse(response.Content);
      var popupJson= doc.RootElement.GetProperty("menu").GetProperty("popup");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-24
        • 1970-01-01
        • 2014-01-24
        • 2020-08-28
        • 2021-12-12
        • 1970-01-01
        相关资源
        最近更新 更多