【问题标题】:Deserialize JSON array of arrays into c# class [duplicate]将数组的JSON数组反序列化为c#类[重复]
【发布时间】:2020-07-01 17:08:22
【问题描述】:

我有一个格式如下的课程:

public class Person 
{
    public string Name {get;set;}
    public int Age {get;set;}
    public string Car {get;set;}
}

我试图从文件中读取 JSON:

using (StreamReader r = new StreamReader(path))
{
    string json = r.ReadToEnd();

    //var items = JsonConvert.DeserializeObject<IEnumerable<Person>>(json);
}

当我得到一个字符串中的 JSON 时,我得到的格式如下:

[
    ["John", 30, "BMW"],
    ["Tim", 45, "Ford"],
    ["Kim", 34, "Toyota"]
]

我以为 JSON 会在 IEnumerable&lt;Person&gt; 中反序列化,但它不能。

使用 Person 类反序列化 JSON 字符串的正确方法是什么?

【问题讨论】:

标签: c# json json.net


【解决方案1】:

由于您的 JSON 中只有没有属性名称的值,您可以将其反序列化为集合对象序列,例如 IEnumerable&lt;string[]&gt;IEnumerable&lt;List&lt;string&gt;&gt;List&lt;List&lt;string&gt;&gt;。然后手动将每个项目解析为Person(假设您对所有项目都有相同的结构,否则您将需要额外的逻辑来检查错误)

var result = JsonConvert.DeserializeObject<IEnumerable<string[]>>(jsonString);
var persons = result
    .Select(item => new Person { Name = item[0], Age = int.Parse(item[1]), Car = item[2] })
    .ToList();

【讨论】:

    【解决方案2】:

    如果您想反序列化为 Person 对象,那么您的数组项需要位于键/值对象结构中,而不是字符串数组。您的 JSON 应如下所示:

    [
      { 
        name: "John", 
        age: 30, 
        car: "BMW" 
      },
      { 
        name: "Tim", 
        age: 45, 
        car: "Ford" 
      },
      { 
        name: "Kim", 
        age: 34, 
        car: "Toyota" 
      }
    ]
    

    编辑: 由于您无法更改输入文件结构,我建议您以IEnumerable&lt;string[]&gt; 的形式阅读。

    然后您可以继续阅读以下内容:

    var rawPersons = JsonConvert.Deserialize<IEnumerable<string[]>>(json);
    

    如果您在 Person 类上创建构造函数,那么它可以从原始 Person 对象填充您的属性:

    public Person(string[] parts) {
        if(parts.Length != 3) {
            throw new ArgumentException("Not a valid person.");
        }
    
        Name = parts[0];
        var validAge = int.TryParse(parts[1], out Age);
        if(!validAge) {
          throw new ArgumentException("Age is not an integer.");
        }
        Car = parts[2];
    }
    

    最后,您可以在原始人物上使用投影来获取 Person 对象的集合。

    var persons = rawPersons.Select(p => new Person(p));
    

    【讨论】:

    • 是的,对不起!这将被完美地反序列化为Person,但我不会将 JSON 作为键/值。我必须阅读该格式的 JSON 文件。
    • 啊,所以您需要使用更自定义的阅读方法来创建 Person 对象。
    • 嗯...可能是动态对象?并手动映射?
    • 我添加了一个示例,说明如何将输入文件和项目读取到 Person 对象列表中。
    • 这似乎是一个很好的解决方案,让我在我的用例中尝试一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    相关资源
    最近更新 更多