[英]Using JSON.NET and C# reading file and deserialize the JSON fails
我有一个名为'movies.json'的JSON文件,其中包含一个对象和一组3部电影。 movies.json中的JSON如下所示:
{
"theMovies": [
{
"name": "Starship Troopers",
"year": 1997
},
{
"name": "Ace Ventura: When Nature Calls",
"year": 1995
},
{
"name": "Big",
"year": 1988
}
]
}
我还有一个名为Movie的课程
public class Movie
{
public string Name { get; set; }
public int Year { get; set; }
}
我试图将文件读入一个字符串,并将JSON反序列化为一种类型的电影,如下所示:
Movie movie1 = JsonConvert.DeserializeObject<Movie>(File.ReadAllText(@"c:\Temp\movies.json"));
和这样:
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);
}
两者都不起作用。 movie1和movie2都没有显示Watch窗口的真实数据:
movie1.Name = null
movie1.Year = 0
movie2.Name = null
movie2.Year = 0
显然有一个内部数组的对象不起作用。 有什么建议么?
完整的JSON文档不是Movie
,它是一个具有属性theMovies
的对象,其中包含Movie
的数组。 因此,您无法将完整的JSON文档反序列化为Movie
,因为其结构与目标类型不匹配。
你可以:
创建一个表示整个文档的类并反序列化该类:
class MyDocument { [JsonProperty("theMovies")] public Movie[] Movies { get; set; } }
然后,您可以访问document.Movies
的第一项
或者获取包含第一部电影的节点,并对其进行反序列化:
var doc = JObject.Parse(File.ReadAllText(@"c:\\Temp\\movies.json")); var theMovies = doc["theMovies"] as JArray; var firstMovie = theMovies[0].ToObject<Movie>();
在JSON,什么都封闭在[ ]
表示集合以及任何包含在{ }
表示对象(见我的答案在这里 )。 因此,您可以看到您有一个包含名为theMovies
的集合的对象,该集合由3个对象(在本例中为电影)组成,每个对象具有2个属性。 如果你在C#术语中考虑这些,你可以有一个类(它将作为根对象,让我们称之为MyJsonDocument
)包含一个IEnumerable<Movie>
(它将充当theMovies
集合)来保存每个Movie
对象。
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; }
}
现在您已经设置了结构:
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})");
}
输出:
Starship Troopers(1997)
Ace Ventura:当自然呼唤时(1995)
大(1988)
另外,您可能还想考虑当某些JSON属性为空时会发生什么(例如,没有列出特定影片的年份)。 您必须将Year
转换为int?
(可以为空的整数)而不是int
。 如果您100%确信JSON中的所有属性将始终填充,那么您可以忽略它。
您的类结构应与您的json文件匹配。
请尝试以下方法:
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);
}
}
您正在尝试将List X对象反序列化为Movie对象,它们不兼容。
var myLibrary = JsonConvert.DeserializeObject<MyLibrary>(File.ReadAllText(@"c:\Temp\movies.json"));
楷模:
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; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.