簡體   English   中英

如何將非關鍵JSON解析為C#類?

[英]How to parse non-key JSON to C# classes?

我從網址獲取Json數據,如下所示。 但是正如您所看到的,Json中沒有鍵名。

例如,“ Flame Towers”是地名值,但沒有任何鍵名。 同樣,“ 2017-02-10”是日期值,“ The Lego Batman Movie 2D”是電影名稱值,但聲明為鍵,[[10:10”]是一個包含電影播放時間的數組。

我嘗試了許多類結構,使用JsonConvert.DeserializeObject<ClassName>(jsonString);將其反序列化為C#類JsonConvert.DeserializeObject<ClassName>(jsonString);

但是每次它返回一個空對象。 還嘗試使用JObject類手動解析,在我看來,這很困惑。

那么,有人可以幫助JsonConvert類解析真正的類結構嗎?

{
    {
        "Flame Towers": {
            "2017-02-10": {
                "The Lego Batman Movie 2D": [
                    "10:10"
                ],
                "Qatil 2D": [
                    "10:30"
                ],
                "Fifty Shades Darker 2D": [
                    "10:30",
                    "11:40",
                    "12:50",
                    "14:00",
                    "15:10",
                    "16:20",
                    "17:30",
                    "18:40",
                    "19:50",
                    "21:00",
                    "22:10",
                    "23:20",
                    "00:30",
                    "01:40"
                ],
                "John Wick: Chapter Two 2D": [
                    "11:00",
                    "12:10",
                    "13:20",
                    "14:30",
                    "15:40",
                    "16:50",
                    "18:00",
                    "20:20",
                    "21:30",
                    "22:40",
                    "23:50",
                    "01:00",
                    "02:10"
                ],
                "The Lego Batman Movie 3D": [
                    "11:00",
                    "12:10",
                    "13:00",
                    "14:10",
                    "15:00",
                    "17:00",
                    "19:00"
                ],
                "Ballerina 3D": [
                    "16:10"
                ],
                "Rings 2D": [
                    "17:55"
                ],
                "Ağanatiq 2D": [
                    "19:55"
                ],
                "Resident Evil: The Final Chapter 3D": [
                    "21:40",
                    "21:00",
                    "23:50",
                    "01:10"
                ],
                "The Great Wall 3D": [
                    "23:10"
                ]
            }
        },
        "Metro Park": {
            "2017-02-10": {
                "John Wick: Chapter Two 2D": [
                    "10:30",
                    "12:50",
                    "15:10",
                    "17:30",
                    "19:50",
                    "22:10",
                    "00:30"
                ],
                "Ağanatiq 2D": [
                    "10:00",
                    "11:50",
                    "13:40",
                    "15:30",
                    "17:20",
                    "19:10",
                    "21:00",
                    "23:00",
                    "00:50"
                ],
                "The Lego Batman Movie 2D": [
                    "10:30"
                ],
                "Fifty Shades Darker 2D": [
                    "11:00",
                    "13:20",
                    "15:40",
                    "18:00",
                    "20:20",
                    "02:00"
                ],
                "Hoqqa 2D": [
                    "11:10",
                    "12:50",
                    "14:30",
                    "16:10",
                    "17:50",
                    "19:30",
                    "21:10",
                    "22:50",
                    "00:30",
                    "02:10"
                ],
                "Naxox 2D": [
                    "11:20",
                    "13:10",
                    "15:00",
                    "16:50",
                    "18:40",
                    "20:30",
                    "22:20",
                    "00:10"
                ],
                "The Lego Batman Movie 3D": [
                    "12:30",
                    "14:30",
                    "16:30",
                    "18:30"
                ],
                "Ballerina 3D": [
                    "20:30"
                ],
                "Resident Evil: The Final Chapter 3D": [
                    "22:40",
                    "00:50"
                ],
                "The Great Wall 3D": [
                    "22:20",
                    "02:30"
                ],
                "Притяжение 3D": [
                    "00:20"
                ]
            }
        }
    }
}

有一種簡單,快捷的方法。 只需在序列化之前從字符串中切除第一個和最后一個{ }符號即可。

if (jsonString.StartsWith("{{") && jsonString.EndsWith("}}"))
    jsonString = jsonString.Substring(2, jsonString.Length - 4);
JsonConvert.DeserializeObject<ClassName>(jsonString);

看起來像是電影院及其活躍節目的集合中的數據,其中最重要的項目“ Flame Towers”是電影院的名稱,“ 2017-02-10”是日期,下面是每個節目/電影,然后是“顯示”時間。

知道這一點,您可以創建與此匹配的數據結構。

...也許是這樣?

    public class Movie : IEnumerable<TimeSpan>
    {

        public Movie(string name, IReadOnlyList<TimeSpan> runTimes)
        {
            this.Name = name;
            this.RunTimes = runTimes;
        }

        public string Name { get; }

        public IReadOnlyList<TimeSpan> RunTimes { get; }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<TimeSpan> GetEnumerator()
        {
            return RunTimes.GetEnumerator();
        }

        public override string ToString()
        {
            return "[Movie] " + Name;
        }

        public static Movie Parse(JProperty data)
        {
            var name = data.Name;
            var runTimes = new List<TimeSpan>();

            foreach (var child in data.Values())
            {
                runTimes.Add(TimeSpan.Parse(child.Value<string>()));
            }

            return new Movie(name, runTimes);
        }
    }


    public class MovieCollectionDate : IEnumerable<Movie>
    {

        public MovieCollectionDate(DateTime date, IReadOnlyList<Movie> movies)
        {
            this.Date = date;
            this.Movies = movies;
        }

        public DateTime Date { get; }

        public IReadOnlyList<Movie> Movies { get; }


        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<Movie> GetEnumerator()
        {
            return this.Movies.GetEnumerator();
        }

        public override string ToString()
        {
            return "[Date] " + Date + " - " + Movies.Count + " show(s)";
        }

        public static MovieCollectionDate Parse(JProperty data)
        {
            var date = DateTime.Parse(data.Name);
            var movies = new List<Movie>();

            foreach (var upperChild in data.Children<JObject>())
            {
                foreach (var child in upperChild.Children())
                {
                    movies.Add(Movie.Parse(child as JProperty));
                }
            }

            return new MovieCollectionDate(date, movies);
        }
    }

    public class MovieTheatre : IEnumerable<MovieCollectionDate>
    {

        public MovieTheatre(string name, IReadOnlyList<MovieCollectionDate> dateAndMovies)
        {
            this.Name = name;
            this.DateAndMovies = dateAndMovies;
        }

        public string Name { get; }
        public IReadOnlyList<MovieCollectionDate> DateAndMovies { get; }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<MovieCollectionDate> GetEnumerator()
        {
            return this.DateAndMovies.GetEnumerator();
        }

        public override string ToString()
        {
            return "[Theatre] " + Name + " - " + DateAndMovies.Count + " open day(s)";
        }


        public static MovieTheatre Parse(JProperty data)
        {
            var name = data.Name;
            var movieCollectionDates = new List<MovieCollectionDate>();
            foreach (var upperChild in data.Children<JObject>())
            {
                foreach (var child in upperChild.Children())
                {
                    movieCollectionDates.Add(MovieCollectionDate.Parse(child as JProperty));
                }
            }

            return new MovieTheatre(name, movieCollectionDates);
        }
    }

    public class MovieTheatreCollection : IEnumerable<MovieTheatre>
    {

        public MovieTheatreCollection(IReadOnlyList<MovieTheatre> movieTheatres)
        {
            this.MovieTheatres = movieTheatres;
        }

        public IReadOnlyList<MovieTheatre> MovieTheatres { get; }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<MovieTheatre> GetEnumerator()
        {
            return this.MovieTheatres.GetEnumerator();
        }

        public override string ToString()
        {
            return "MovieTheatreCollection: Containing " + MovieTheatres.Count + " movie theatre(s)";
        }

        public static MovieTheatreCollection Parse(JObject data)
        {
            var theatres = new List<MovieTheatre>();
            foreach (var child in data.Children().Cast<JProperty>())
            {
                theatres.Add(MovieTheatre.Parse(child));
            }
            return new MovieTheatreCollection(theatres);
        }
    }

這顯然不是解決問題的最優雅的方法。 但是看到這種“無密鑰”的json不會在沒有某種黑客手段的情況下正確地反序列化。 創建一個滿足您需求的數據結構(不幸的是,更多的人工工作)至少會起作用;)

您可以將上面的代碼與以下代碼一起使用:

JObject obj = JObject.Parse(... the json string you had above ...)

MovieTheatreCollection movieTheatres = MovieTheatreCollection.Parse(obj);

foreach (var movieTheatre in movieTheatres)
{
    Console.WriteLine(movieTheatre);
    foreach (var openDay in movieTheatre)
    {
        Console.WriteLine("   " + openDay);
        foreach (var movie in openDay)
        {
            Console.WriteLine("      " + movie);
            foreach (var runtime in movie) Console.WriteLine("        - " + runtime);
        }
    }                
}

最后,就像上面答案中提到的“ Just Shadow”一樣,json格式錯誤,包含多余的花括號,需要將其刪除,否則對象將無法正確解析。

解析此問題的難看但合理的緊湊方法是:

static void Main(string[] args)
    {                   
        var jo = JObject.Parse(File.ReadAllText("data.json").Trim('{').Trim('}'));
        foreach (var place in jo)
        {
            Console.WriteLine($"Place: {place.Key}");
            foreach (var dateOrMovie in place.Value.Children<JProperty>())
            {
                Console.WriteLine($"\tDate: {dateOrMovie.Name}");
                var movies = dateOrMovie.Children<JObject>().First().Children<JProperty>();
                foreach (var movie in movies)
                {
                    Console.WriteLine($"\t\t{movie.Name}");
                    foreach (JValue time in movie.Children<JArray>().First())
                    {
                        Console.WriteLine($"\t\t\t{time.Value}");
                    }
                }
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM