【问题标题】:Finding specific values in JSON.NET with C#使用 C# 在 JSON.NET 中查找特定值
【发布时间】:2014-01-19 10:27:29
【问题描述】:

我一直在制作 Minecraft 启动器。我有一个很长的 JSON 文件,其中包含启动 one 版本所需的所有库。此代码示例:

{
  "id": "1.6.2",
  "time": "2013-08-06T14:00:00+03:00",
  "releaseTime": "2013-07-05T16:09:02+03:00",
  "type": "release",
  "minecraftArguments": "--username ${auth_player_name} --session ${auth_session} --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}",
  "libraries": [
    {
      "name": "net.sf.jopt-simple:jopt-simple:4.5"
    },
    {
      "name": "com.paulscode:codecjorbis:20101023"
    },

所以你可以看到有一个名为libraries的数组。我可以使用 foreach 很好地查询“名称”中的值,但有时这会发生在 json 中:

{
  "name": "org.lwjgl.lwjgl:lwjgl:2.9.0",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "osx",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
},

如您所见,内部有一个名为rules 的数组。我需要在rules 中的os 中找到name 的值。我尝试过的任何事情都出现了异常并且不起作用。这是我目前用于解析代码的代码:

    foreach (JToken lib in profilejsono["libraries"])
    {
        if ((lib["rules"][1]["os"].ToString() == "osx") || (lib["rules"][1]["os"].ToString() == "linux"))
        {
            availableLibs.Add(lib["name"].ToString());
        }
    }

代码的重点是不要添加适用于 OSX 或 Linux 的库(我稍后会添加该功能)。我该怎么做?

【问题讨论】:

  • 你能分享一下你得到的确切例外吗?
  • System.NullReferenceException(对象引用未设置为对象的实例。
  • 您收到此错误是因为您尝试达到["os"] 值的方式。 foreach 循环返回每个 Jtoken,但实际上只有一个项目会返回 lib["rules"][1]["os"] 的值,否则你会得到 null,因为该项目没有 "os" 属性。
  • 有很多方法可以解决这个问题,但最简单的方法是额外检查是否有lib["rules"].count >= 2,因为你想要第二个索引为[1]的元素,然后检查它是否有@ 987654337@ property 等等...我不说这是最好的方法,只是为了让您走上正确的轨道..
  • 我的建议是在您的工作示例中发布新问题,无论您认为它有多糟糕,并寻求帮助以改进它。在这个问题中,您首先会发现为什么会出现此错误,如果我是您,我会问另一个问题,以了解处理这种情况的最佳方法。

标签: c# json linq json.net


【解决方案1】:

解决您的问题的一种可能方法是对操作系统名称的检查进行概括(并使其与规则节点深度无关)。我想您有一些库对象,因为您需要将 JSON 输入字符串反序列化为某个对象。以下代码仅为具有 rule 节点和 os 节点的库节点提供了库名称:

JSON 测试输入文件lib1.json

{
  "name": "lib1",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "windows",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
}

JSON 测试输入文件 lib2.json

{
  "name": "lib2",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "osx",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
}

JSON 测试输入文件 lib3.json

{
  "name": "lib3",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "linux",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
}

JSON 测试输入文件 lib4.json

{
  "name": "lib4",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow"
    }
  ]
}

描述 library 节点的 JSON 帮助器对象,需要反序列化 JSON 输入:

// helper classes describing the library object (for the JSON deserialization)
public class Library
{
    public String Name { get; set; }
    public Rules[] Rules { get; set; }
}

public class Rules
{
    public String Action { get; set; }
    public Os Os { get; set; }
}

public class Os
{
    public String Name { get; set; }
    public String Version { get; set; }
}

仅获取匹配库的代码:

var jsonInput = @"d:\temp\json.net\lib{0}.json";
try
{
    // load libraries / deserialize json
    var libraries = new List<Library>();
    Enumerable.Range(1, 4).ToList().ForEach(index => 
    {
        var json = File.ReadAllText(String.Format(jsonInput, index));
        libraries.Add(JsonConvert.DeserializeObject<Library>(json));
    });
    // OS names to check if present in the current rules
    var osNames = new List<String> { "osx", "linux" };
    // check each library
    foreach (var library in libraries)
    {
        // do we have rules?
        if (library.Rules.Length > 0)
        {
            // get all non-empty OS nodes
            var existingOsNodes = library.Rules.Where (r => r.Os != null).Select (r => r.Os).ToList();
            // check for allowed OS name
            var osIsPresent = existingOsNodes.Where (node => osNames.Contains(node.Name.ToLower())).Select (node => node.Name);
            if (osIsPresent.Any())
            {
                Console.WriteLine(library.Name);
            }
        }
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

四个给定输入文件的输出是:

lib2
lib3

【讨论】:

  • 问题是通用库没有rules元素,只有`name。
  • Soo 如果某些东西不存在,您如何检查它?请更彻底地解释此事,并在您的问题中提供更多示例。
  • 我所做的是检查 ArgumentNullException,这意味着它没有找到指定的元素。因此,没关系。否则,如果它确实找到了 rules 元素,它什么也不做。
  • 我的答案中的代码在您描述的每种情况下都能正常工作(无论存在和缺失哪个节点)。您是否尝试过它是否适合您?
  • 不,我没有,因为我有 JSON.NET,所以你的大部分代码都是无关紧要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
相关资源
最近更新 更多