4

I have a class in the format:

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

What i tried to read the JSON from a file:

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

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

When I got the JSON in a string I got that in the format below:

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

I thought that JSON would be Deserialize in that IEnumerable<Person>, but it couldn't.

What is the correct way to deserialize the JSON string with that Person class?

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
Rasik
  • 1,961
  • 3
  • 35
  • 72

2 Answers2

2

Since you have only values without properties names in your JSON, you can deserialize it into sequence of collection objects, like IEnumerable<string[]>, IEnumerable<List<string>> or List<List<string>>. Then parse every item to Person manually (assuming that you have the same structure for all items, otherwise you'll need an additional logic for checking an errors)

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();
Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
0

If you want to deserialize into a Person object, then your array items need to be in a key/value object structure instead of an array of strings. Your JSON should be the following:

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

EDIT: Since you are unable to change the input file structure, I would recommend reading in as an IEnumerable<string[]>.

Then you can proceed to read with the following:

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

If you create a constructor on your Person class, then it can populate your properties from the raw Person object:

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];
}

Lastly, you can use a projection on your raw persons to get a collection of Person objects.

var persons = rawPersons.Select(p => new Person(p));
Cameron Tinker
  • 9,634
  • 10
  • 46
  • 85