Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用C在JSON.NET中查找特定值#_C#_Json_Linq_Json.net - Fatal编程技术网

C# 使用C在JSON.NET中查找特定值#

C# 使用C在JSON.NET中查找特定值#,c#,json,linq,json.net,C#,Json,Linq,Json.net,我一直在做一个地雷发射器。我有一个长JSON文件,其中包含启动一个版本所需的所有库。此代码的示例: { "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_se

我一直在做一个地雷发射器。我有一个长JSON文件,其中包含启动一个版本所需的所有库。此代码的示例:

{
  "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"
    },
因此,您可以看到有一个名为
库的数组。我可以使用foreach很好地查询“name”中的值,但有时json中会出现这种情况:

{
  "name": "org.lwjgl.lwjgl:lwjgl:2.9.0",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "osx",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
},
如您所见,内部有一个名为
rules
的数组。我需要在
os
inside
rules
中找到
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的,则不添加库(稍后我将添加该功能)。如何做到这一点?

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

JSON测试输入文件lib1.JSON:

JSON测试输入文件lib2.JSON:

JSON测试输入文件lib3.JSON:

JSON测试输入文件lib4.JSON:

描述库节点的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);
}

您会分享您得到的确切异常吗?System.NullReferenceException(对象引用未设置为对象的实例。您得到此错误是因为您试图达到
[“os”]
值的方式。
foreach
循环返回每个
Jtoken
,但实际上只有一个项将返回
库的值[“rules”][1][“os”]
否则您会得到
null
,因为此项没有属性
“os”
。有很多方法可以管理此项,但最简单的方法就是对
lib[“rules”]进行一些额外检查。count>=2
,因为您需要第二个具有索引的元素
[1]
然后,检查它是否有
“操作系统"
property等等……我不说这是最好的方法,只是为了让你走上正确的轨道……我的建议是,不管你认为它有多糟糕,都用你的工作示例发布新问题,并寻求改进方面的帮助。在这个问题中,你首先要找出为什么会出现这个错误,如果我是你,我会问另一个问题关于处理这种情况的最佳方法,请继续。问题是,通用库没有
规则
元素,只有'name.Soo。如果没有,您如何检查它?请更彻底地解释问题,并在您的问题中提供更多示例。我所做的是检查ArgumentNullException,这意味着它没有异常找到指定的元素。这样就可以了。否则,如果它确实找到
规则
元素,它什么也不做。我的答案中的代码在您描述的每种情况下都能正确工作(无论存在和缺少哪个节点).你试过了吗?没有,因为我有JSON.NET,所以你的大部分代码都是无关的。
{
  "name": "lib3",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow",
      "os": {
        "name": "linux",
        "version": "^10\\.5\\.\\d$"
      }
    }
  ]
}
{
  "name": "lib4",
  "rules": [
    {
      "action": "allow"
    },
    {
      "action": "disallow"
    }
  ]
}
// 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