如何反序列化具有动态(数字)键名的子对象?

Posted

技术标签:

【中文标题】如何反序列化具有动态(数字)键名的子对象?【英文标题】:How can I deserialize a child object with dynamic (numeric) key names? 【发布时间】:2014-09-06 10:50:08 【问题描述】:

如何反序列化此 JSON 数据? “100034”等键本质上是动态的。


    "users" : 
        "100034" : 
            "name"  : "tom",
            "state" : "WA",
            "id"    : "cedf-c56f-18a4-4b1"
        ,
        "10045" : 
            "name"  : "steve",
            "state" : "NY",
            "id"    : "ebb2-92bf-3062-7774"
        ,
        "12345" : 
            "name"  : "mike",
            "state" : "MA",
            "id"    : "fb60-b34f-6dc8-aaf7"
        
    

有没有一种方法可以直接访问具有名称、状态和 ID 的每个对象?

【问题讨论】:

Deserialize JSON into C# dynamic object?的可能重复 这里不是重复的原因..它的非法c#标识符和动态也是 【参考方案1】:

对于属性名称可变的 JSON 对象,您可以使用 Dictionary<string, T> 代替常规类,其中 T 是表示项目数据的类。

像这样声明你的类:

class RootObject

    public Dictionary<string, User> users  get; set; 


class User

    public string name  get; set; 
    public string state  get; set; 
    public string id  get; set; 

然后像这样反序列化:

RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);

演示:

class Program

    static void Main(string[] args)
    
        string json = @"
        
            ""users"": 
                ""10045"": 
                    ""name"": ""steve"",
                    ""state"": ""NY"",
                    ""id"": ""ebb2-92bf-3062-7774""
                ,
                ""12345"": 
                    ""name"": ""mike"",
                    ""state"": ""MA"",
                    ""id"": ""fb60-b34f-6dc8-aaf7""
                ,
                ""100034"": 
                    ""name"": ""tom"",
                    ""state"": ""WA"",
                    ""id"": ""cedf-c56f-18a4-4b1""
                
            
        ";

        RootObject root = JsonConvert.DeserializeObject<RootObject>(json);

        foreach (string key in root.users.Keys)
        
            Console.WriteLine("key: " + key);
            User user = root.users[key];
            Console.WriteLine("name: " + user.name);
            Console.WriteLine("state: " + user.state);
            Console.WriteLine("id: " + user.id);
            Console.WriteLine();
        
    

输出:

key: 10045
name: steve
state: NY
id: ebb2-92bf-3062-7774

key: 12345
name: mike
state: MA
id: fb60-b34f-6dc8-aaf7

key: 100034
name: tom
state: WA
id: cedf-c56f-18a4-4b1

【讨论】:

正如我之前提到的,键是动态的。在这种情况下,您的解决方案将如何工作?我怎么知道要传递什么作为密钥? 你试过了吗?字典在反序列化期间处理动态键。通过遍历字典中的Keys 集合来发现键是什么是微不足道的。我在答案中添加了一个演示。 @BrianRogers 谢谢,罗杰这对我帮助很大。但是你能告诉我我们是否收到一个没有任何密钥但在其内部细节中有密钥的响应。我找不到办法。例如就我而言,我收到此类/相同类型的响应,但响应对象没有密钥。那么我将如何反序列化它,因为数据即将到来,但在反序列化它之后,它给出了 null。 (我的响应对象的形状类似于 "10101":"name":"aaa", "desc":"aaa111","20202":"name":"bbb", "desc" :"bbb222" @MalikAsif 将此作为新问题发布,以便您可以完整描述您面临的问题。如果您需要提供上下文,可以链接回此问题。 你救了很多人,我相信布赖恩。谢谢你:)【参考方案2】:

    添加包 System.Web.Script.Serialization;

    假设您的 JSON 包含 Internet 用户列表我创建了一个这样的类..

    public class internet
    
       public List<User> Users  get; set; 
    ;
    public class User
    
       public String Name  get; set; 
       public String Id  get; set; 
       public String State  get; set; 
    ;
    

假设您的 JSON 字符串位于变量“JSONDATA”中,请按照以下代码将您的 JSON 数据序列化为类对象。

     var JSONDATA = /* Your JSON String */;
     javascriptSerializer serializer = new JavaScriptSerializer();
     internet Intr = serializer.Deserialize<internet>(JSONDATA);

【讨论】:

这不起作用,因为 JSON 不包含列表(数组)。

以上是关于如何反序列化具有动态(数字)键名的子对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何反序列化没有字段名的 JSON

如何反序列化具有可序列化对象数组的类

如何反序列化具有相同名称但不同类型的 API 响应

如何从动态对象中获取反序列化的 xml 属性

如何让 ServiceStack 序列化/反序列化具有正确类型的 expando 对象

反序列化