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