Reputation: 161
I have a JSON file named 'movies.json' which contains an object and an array of 3 movies. The JSON in movies.json looks like this:
{
"theMovies": [
{
"name": "Starship Troopers",
"year": 1997
},
{
"name": "Ace Ventura: When Nature Calls",
"year": 1995
},
{
"name": "Big",
"year": 1988
}
]
}
I also have a class named Movie
public class Movie
{
public string Name { get; set; }
public int Year { get; set; }
}
I am trying to read the file into a string and deserialize the JSON to a type of Movie like this:
Movie movie1 = JsonConvert.DeserializeObject<Movie>(File.ReadAllText(@"c:\Temp\movies.json"));
and like this:
using (StreamReader file = File.OpenText(@"c:\Temp\movies.json"))
{
JsonSerializer serializer = new JsonSerializer();
Movie movie2 = (Movie)serializer.Deserialize(file, typeof(Movie));
Console.WriteLine(movie2.Name);
Console.WriteLine(movie2.Year);
}
Neither one works. Both movie1 and movie2 show no real data the Watch window:
movie1.Name = null
movie1.Year = 0
movie2.Name = null
movie2.Year = 0
Apparently having an object with an array inside is not working. Any suggestions?
Upvotes: 2
Views: 1704
Reputation: 6565
In JSON, anything enclosed in [ ]
denotes a collection and anything enclosed in { }
denotes an object (see my answer here). So, you can see that you have an object containing a collection called theMovies
, consisting of 3 objects (in this case, movies) with 2 properties each. If you think of these in C# terms, you could have a class (which would act as the root object, let's call it MyJsonDocument
) containing an IEnumerable<Movie>
(which would act as theMovies
collection) to hold each Movie
object in.
public class MyJsonDocument
{
// JsonProperty indicates how each variable appears in the JSON, _
// so the deserializer knows that "theMovies" should be mapped to "Movies". _
// Alternatively, your C# vars should have the same name as the JSON vars.
[JsonProperty("theMovies")]
public List<Movie> Movies { get; set; }
}
public class Movie
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("year")]
public int Year { get; set; }
}
Now that you have your structure set up:
var myJsonDocument = JsonConvert.DeserializeObject<MyJsonDocument>(File.ReadAllText(@"C:\Users\trashr0x\Desktop\movies.json"));
foreach(Movie movie in myJsonDocument.Movies)
{
Console.WriteLine(string.Format("{0} ({1})", movie.Name, movie.Year));
// or with C# 6.0:
Console.WriteLine($"{movie.Name} ({movie.Year})");
}
Output:
Starship Troopers (1997)
Ace Ventura: When Nature Calls (1995)
Big (1988)
As an aside, you might also want to consider what happens when some of the JSON properties are empty (for example, no year listed for a particular movie). You would have to convert Year
to be an int?
(nullable integer) instead of an int
. If you are 100% confident that all properties in the JSON will be always populated then you can ignore this.
Upvotes: 3
Reputation: 292405
The full JSON document is not a Movie
, it's an object with a property theMovies
that contains an array of Movie
s. So you can't deserialize the full JSON document into a Movie
, since its structure doesn't match the target type.
You can either:
create a class that represents the whole document and deserialize this class:
class MyDocument
{
[JsonProperty("theMovies")]
public Movie[] Movies { get; set; }
}
You can then access the first item in document.Movies
or get the node that contains the first movie, and deserialize it:
var doc = JObject.Parse(File.ReadAllText(@"c:\Temp\movies.json"));
var theMovies = doc["theMovies"] as JArray;
var firstMovie = theMovies[0].ToObject<Movie>();
Upvotes: 4
Reputation: 12196
You're trying to deserialize List X object to Movie object, which they are not compatible.
var myLibrary = JsonConvert.DeserializeObject<MyLibrary>(File.ReadAllText(@"c:\Temp\movies.json"));
Models:
class MyLibrary
{
public List<Movie> theMovies { get; set; }
}
public class Movie
{
public string name { get; set; } // Changed to lower case, as the json representation.
public int year { get; set; }
}
Upvotes: 1
Reputation: 28737
Your class structure should match your json file.
Try the following:
class MovieList
{
public List<Movie> TheMovies {get; set;}
}
public class Movie
{
public string Name { get; set; }
public int Year { get; set; }
}
using (StreamReader file = File.OpenText(@"c:\Temp\movies.json"))
{
JsonSerializer serializer = new JsonSerializer();
MovieList movies = (MovieList)serializer.Deserialize(file, typeof(MovieList));
foreach(var movie in movies.TheMovies)
{
Console.WriteLine(movie.Name);
Console.WriteLine(movie.Year);
}
}
Upvotes: 1