如何将非密钥JSON解析为C#类?

时间:2017-02-10 07:16:30

标签: c# json parsing json.net

我从url获取Json数据如下。但是如你所见,Json中没有关键名称。

例如,"火焰塔"是地名名称值,但没有任何键名。同样," 2017-02-10"是日期值,"乐高蝙蝠侠电影2D"是电影名称值,但它被声明为关键,[" 10:10"]是一个数组包含电影会话时间。

我尝试了许多类结构,使用JsonConvert.DeserializeObject<ClassName>(jsonString);

将其反序列化为C#类

但每次返回一个null对象。还尝试用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"
                ]
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

这样做有一种简单,苛刻和快速的方法。在序列化之前,只需从字符串中剪切第一个和最后一个{ }个符号。

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

答案 1 :(得分:0)

它看起来像一组电影院及其活动节目的数据,其中顶部项目“火焰塔”是电影院的名称,“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格式错误,包含需要删除的额外大括号或对象无法正确解析。

答案 2 :(得分:0)

解析这个问题的一个丑陋但相当紧凑的方法是:

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}");
                    }
                }
            }
        }
    }