【问题标题】:Getting data out of a Dictionary<string,object>从 Dictionary<string,object> 中获取数据
【发布时间】:2014-08-26 09:24:32
【问题描述】:

我使用 .NET 通过 3.5 System.Web.Extensions 程序集中的 System.Web.Script.Serialization.JavaScriptSerializer 类型将 JSON 字符串转换为 Dictionary。

我将 JSON 数据保存在字典对象中,如下所示:

        // Simple POST request
        using (System.Net.WebClient wb = new System.Net.WebClient())
        {
            // Random user data API - http://randomuser.me/
            string url = "http://api.randomuser.me/";

            var data = new System.Collections.Specialized.NameValueCollection();
            var responseStringJson = Encoding.Default.GetString(wb.UploadValues(url, "POST", data));

            var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            Dictionary<string, object> Results = jsSerializer.Deserialize<dynamic>(responseStringJson);
        }

JSON 数据示例

{
  results: [{
    user: {
      gender: "male",
      name: {
        title: "mr",
        first: "patrick",
        last: "coleman"
      },
      location: {
        city: "stockton",
        state: "minnesota",
        zip: "10532"
      },
      email: "patrick.coleman45@example.com",
      username: "ticklishostrich48",
      password: "darkknight55",
      salt: ">DyBf9aih",
      md5: "5d6bf4508070fba41e2d602c847cdbd9",
      sha1: "19e5b0b59e6c86dbf370c431a7edb2aa4f1420a6",
      sha256: "9434e04d307839d9b6411254007072412c11f7e6b5d8fd848e56fe5f0c660a04"
    },
    version: "0.4"
  }]
}

如何通过键值访问数据? 我会做类似的事情:

Results["results"]["version"]
Results["results"]["user"]["name"]["first"]

在此先感谢,最好的问候,克里斯蒂安。

【问题讨论】:

    标签: c# json object dictionary


    【解决方案1】:

    如果您稍微修改一下,您的原始方法将起作用:

    // Simple POST request
    using (System.Net.WebClient wb = new System.Net.WebClient())
    {
        // Random user data API - http://randomuser.me/
        string url = "http://api.randomuser.me/";
    
        var data = new System.Collections.Specialized.NameValueCollection();
        var responseStringJson = Encoding.Default.GetString(wb.UploadValues(url, "POST", data));
    
        var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        var results = jsSerializer.Deserialize<dynamic>(responseStringJson);
    
        // Note that the following works, because Console.WriteLine
        // automatically formats those objects to a string. If you want
        // to use these anywhere else, you will have to cast/convert the
        // values every time you access them.
        Console.WriteLine(results["results"][0]["version"]);
        Console.WriteLine(results["results"][0]["user"]["name"]["first"]);
        Console.ReadLine();
    }
    

    不过,我建议您创建一些强类型类,然后在项目中使用它们。例如,如果您将 API url 放入 http://json2csharp.com/ 并将这些类添加到您的项目中,则读取数据的代码看起来会有些不同:

    // Simple POST request
    using (System.Net.WebClient wb = new System.Net.WebClient())
    {
        // Random user data API - http://randomuser.me/
        string url = "http://api.randomuser.me/";
    
        var data = new System.Collections.Specialized.NameValueCollection();
        var responseStringJson = Encoding.Default.GetString(wb.UploadValues(url, "POST", data));
    
        var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        var results = jsSerializer.Deserialize<RootObject>(responseStringJson);
    
        Console.WriteLine(results.results[0].version);
        Console.WriteLine(results.results[0].user.name.first);
        Console.ReadLine();
    }
    

    最大的优点是您可以向代理类添加类型转换,而不必每次访问字典中的值时都这样做,并且您可以获得对对象属性的完整 IDE 和编译器支持(更少的拼写错误):

    【讨论】:

    • 谢谢汉吉。我使用了您建议的类型化类。
    【解决方案2】:

    如果每个键的值也是一个字典,那么您必须在声明中指定它。不确定您使用的反序列化器是否支持它,但请尝试一下。

    Dictionary<string, Dictionary<string, object>>
    

    我不建议立即尝试检索完整对象,这可能适用于单个嵌套字典,但可能存在复杂性限制。最好遍历字典中的每个KeyValuePair,如果该值是字典类型,那么强制转换就是这样并单独处理它。这样,反序列化器就不必假定所有值都是定义的字典。

    【讨论】:

    • 每个键的值也不是字典。我用 JSON 数据示例更新了我的帖子。
    【解决方案3】:

    如何通过键值访问数据?我会这样做:
    Results["results"]["user"]["name"]["first"]

    这种语法在 C# 中是不可能的,因为变量是强类型的。 实际上,正如hangy 解释的那样,这 可能使用 .net 4.0 中的新动态关键字,您已经在问题中使用了该关键字。 根据this related answer,您需要做的就是使用System.Web.Helpers.Json.Decode() 反序列化您的Json 对象,它将返回一个dynamic 对象,您应该可以像这样访问它:Results.results.user.name.first


    不使用 net 4.0 动态转换,你也可以写一个这样的函数:

     Results.GetValue("results","user","name","first");
    

    您可以将此方法编写为字典的extension method

    public static class JsonNestedDictionaryExtensions
    {
        public static Object GetValue(this Dictionary<String,Object> dict, params string[] keys)
        {
            Object dictObject = dict;
            String lastKey = "";
            foreach (string key in keys)
            {
                 if (!dictObject is Dictionary<String,Object>)
                     throw new ArgumentException(key+ " cannot be accessed because "+lastKey+" is not a dictionary");
                 dict = (Dictionary<String,Object>) dictObject;
    
                 dictObject = dict["key"];
                 lastKey = key;
            }
    
            return dictObject;
        }
    }
    

    【讨论】:

    • 如果他们只是将对象用作dynamic 而不是将其转换为Dictionary&lt;string, object&gt;,它确实有效。但这并不是处理这些数据的好方法。 ;)
    • 谢谢,我完全忘记了这个新功能。
    猜你喜欢
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多