繁体   English   中英

使用JSON.NET和C#读取文件并反序列化JSON失败

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM