大麻烦。又是 Vk Api
Big trouble. And Vk Api Again
之前一切都很好。我可以反序列化任何 JSON。但是现在我遇到了json,这让我很抓狂。我正在尝试获取用户歌曲。所以现在我需要你的帮助。
这是我的 JSON :(对 json 感到抱歉)(在某些网址前加斜线,因为我名气不大)
response: {
count: 529,
items: [{
id: '34',
photo: 'http://cs617119.v...7/jlKfbdpqdnI.jpg',
name: 'Татьяна Плуталова',
name_gen: 'Татьяны'
}, {
id: 326503650,
owner_id: 34,
artist: 'Ocean Jet',
title: 'Distant',
duration: 229,
url: 'http://cs1-50v4.v...ETD5kMP2-rzbQLisQ',
lyrics_id: 134538662,
genre_id: 17
}, {
id: 321364793,
owner_id: 34,
artist: 'Aaron Embry',
title: 'The Raven's Song',
duration: 145,
url: 'http://cs1-35v4.v...GRtlpummhArtvlRPg',
genre_id: 9
}, {
id: 318936948,
owner_id: 34,
artist: 'The Smiths',
title: 'How Soon Is Now',
duration: 233,
url: 'http://cs1-45v4.v...8Bqm9Z_ja-S43xffw',
genre_id: 9
}]}
这是我的反序列化类
public class SongData2
{
[JsonProperty(PropertyName = "items")]
public List<SongMaders> songs { get; set; }
public class SongMaders
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "artist")]
public string Artist { get; set; }
[JsonProperty(PropertyName = "title")]
public string SongName { get; set; }
[JsonProperty(PropertyName = "url")]
public string SongUri { get; set; }
[JsonProperty(PropertyName = "dutation")]
public int Duration { get; set; }
[JsonProperty(PropertyName = "owner_id")]
public int OwnerId { get; set; }
[JsonProperty(PropertyName = "lyrics_id")]
public int LyricsId { get; set; }
[JsonProperty(PropertyName = "genre_id")]
public int GenreId { get; set; }
}
我需要先获取用户的属性,然后再获取一些自定义类,但它们也无法正常工作。用户属性 - 这是姓名、照片等的位置。
这是我的反序列化代码:
private void Page1_Loaded(object sender, RoutedEventArgs e)
{
WebClient AudioWC = new WebClient();
AudioWC.DownloadStringCompleted += AudioWC_DownloadStringCompleted;
AudioWC.DownloadStringAsync(new Uri(uri));
}
private void AudioWC_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
JObject jobject = JObject.Parse(e.Result);
JArray array = (JArray)jobject["response"]["items"];
MessageBox.Show(array.ToString());
var answer = (SongData2)JsonConvert.DeserializeObject<SongData2>(e.Result);
foreach (SongData2.SongMaders songs in answer.songs)
{
SongData.SongMaders usersongs = new SongData.SongMaders();
usersongs.Artist = songs.Artist;
usersongs.Duration = songs.Duration;
usersongs.SongUri = songs.SongUri;
usersongs.Id = songs.Id;
usersongs.SongName = songs.SongName;
usersongscollforbinding.Add(usersongs);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
this.SpinningAnimation.Stop();
this.AnimEllipse.Visibility = Visibility.Collapsed;
}
UserSongsList.ItemsSource = usersongscollforbinding;
}
希望你能帮助我。你是我最后的希望。
您的 class 表示您的 JSON 结构不正确。请记住,每个 json 对象都需要映射到一个 c# 对象。
这个结构最能代表您的json,您错过了根对象和响应对象。我添加了那些。
public class SongRoot
{
public SongResponse response {get;set;} // maps to { response: { ... }}
}
public class SongResponse {
public int count {get;set;} // maps to count: 529
public List<SongData2> items {get;set;} // maps to items: [{ ... }]
}
public class SongData2
{
public int Id { get; set; } // maps to id: '34',
public string Artist { get; set; } // maps to artist: 'Ocean Jet',
[JsonProperty(PropertyName = "title")]
public string SongName { get; set; }
[JsonProperty(PropertyName = "url")]
public string SongUri { get; set; }
public int Duration { get; set; }
[JsonProperty(PropertyName = "owner_id")]
public int OwnerId { get; set; }
[JsonProperty(PropertyName = "lyrics_id")]
public int LyricsId { get; set; }
[JsonProperty(PropertyName = "genre_id")]
public int GenreId { get; set; }
}
为了序列化您的 JSON 字符串,我使用了以下行:
var root = (SongRoot) JsonConvert.DeserializeObject<SongRoot>(e.Result);
这在 root
中为我提供了 SongRoot
的实例,而 root.response.items
将使您能够访问 4 SongData
classes.
请注意,我必须在您的 JSON 中添加开始 {
和结束 }
,否则它将无效。
这里有几个问题:
您的 json 缺少外括号。如果这不是 copy/paste 错误,您将需要以某种方式解决此问题,例如将 JObject.Parse()
替换为:
public static JObject ParseWithMissingBraces(string json)
{
return JObject.Parse(AddMissingOuterBraces(json));
}
public static string AddMissingOuterBraces(string json)
{
for (int i = 0; i < json.Length; i++)
{
if (char.IsWhiteSpace(json[i])
|| json[i] == '\t'
|| json[i] == '\r'
|| json[i] == '\n'
|| json[i] == '[=10=]')
continue;
if (json[i] == '['
|| json[i] == '{')
return json;
return string.Format("{{{0}}}", json);
}
return json;
}
字符串文字 'The Raven's Song'
包含未转义的嵌入引号。这看起来是生成 json 的系统错误。它应该是 'The Raven\u0027s Song'
或 "The Raven's Song"
这可能是因为 json 是用单引号 ('
) 包围的字符串创建的,而 json standard 指定了双引号引用字符 ("
)。我建议您查看此 json 提供者的文档,看看是否有任何方法可以生成正确转义的字符串,因为如果不编写您自己的 json 解析器,则无法在客户端轻松修复此问题.
数组items
实际上看起来是一个多态数组。第一个条目看起来是有关服务用户的信息;随后的条目看起来是关于歌曲的信息。也许这是一个播放列表,第一个条目是播放列表的所有者?
无论如何,您需要将用户信息过滤到一个单独的 "bucket" 中,以将其与歌曲信息区分开来。以下 class 层次结构和 JsonConverter
可以解决问题:
public abstract class ResponseData
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
}
public class SongData : ResponseData
{
[JsonProperty(PropertyName = "artist")]
public string Artist { get; set; }
[JsonProperty(PropertyName = "title")]
public string SongName { get; set; }
[JsonProperty(PropertyName = "url")]
public string SongUri { get; set; }
[JsonProperty(PropertyName = "duration")]
public int Duration { get; set; }
[JsonProperty(PropertyName = "owner_id")]
public int OwnerId { get; set; }
[JsonProperty(PropertyName = "lyrics_id")]
public int LyricsId { get; set; }
[JsonProperty(PropertyName = "genre_id")]
public int GenreId { get; set; }
}
public class UserData : ResponseData
{
[JsonProperty(PropertyName = "photo")]
public string Photo { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "name_gen")]
public string NameGen { get; set; }
}
public class SongList
{
[JsonProperty(PropertyName="count")]
public int Count { get; set; }
[JsonIgnore]
public List<SongData> Songs { get; set; }
[JsonIgnore]
public List<UserData> Users { get; set; }
[JsonProperty(PropertyName = "items")]
public ResponseData [] Items
{
get
{
return (Users ?? Enumerable.Empty<UserData>()).Cast<ResponseData>().Concat((Songs ?? Enumerable.Empty<SongData>()).Cast<ResponseData>()).ToArray();
}
set
{
Songs = (value ?? Enumerable.Empty<ResponseData>()).OfType<SongData>().ToList();
Users = (value ?? Enumerable.Empty<ResponseData>()).OfType<UserData>().ToList();
}
}
}
public class ResponseDataConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(ResponseData).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
if (item["name"] != null)
{
return item.ToObject<UserData>();
}
else
{
return item.ToObject<SongData>();
}
}
public override void WriteJson(JsonWriter writer,
object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
请注意,为清楚起见,我重命名了您的一些 class 元素和属性,并将嵌套的 class 元素移出了它们的容器。
您的 json 包含一个额外的间接级别,其中包含一个字段 response
:
{
response: {
}
}
这似乎没有增加任何价值,所以您需要从这个包装器中提取有用的数据。
将以上所有内容放在一起,下面从该响应中提取 List<SongData>
和 List<UserData>
假设引用问题已解决:
var json = e.Result;
var jobject = ParseWithMissingBraces(json);
var serializer = new JsonSerializer();
serializer.Converters.Add(new ResponseDataConverter());
var songList = jobject["response"].ToObject<SongList>(serializer);
var songs = songList.Songs;
var users = songList.Users;
之前一切都很好。我可以反序列化任何 JSON。但是现在我遇到了json,这让我很抓狂。我正在尝试获取用户歌曲。所以现在我需要你的帮助。 这是我的 JSON :(对 json 感到抱歉)(在某些网址前加斜线,因为我名气不大)
response: {
count: 529,
items: [{
id: '34',
photo: 'http://cs617119.v...7/jlKfbdpqdnI.jpg',
name: 'Татьяна Плуталова',
name_gen: 'Татьяны'
}, {
id: 326503650,
owner_id: 34,
artist: 'Ocean Jet',
title: 'Distant',
duration: 229,
url: 'http://cs1-50v4.v...ETD5kMP2-rzbQLisQ',
lyrics_id: 134538662,
genre_id: 17
}, {
id: 321364793,
owner_id: 34,
artist: 'Aaron Embry',
title: 'The Raven's Song',
duration: 145,
url: 'http://cs1-35v4.v...GRtlpummhArtvlRPg',
genre_id: 9
}, {
id: 318936948,
owner_id: 34,
artist: 'The Smiths',
title: 'How Soon Is Now',
duration: 233,
url: 'http://cs1-45v4.v...8Bqm9Z_ja-S43xffw',
genre_id: 9
}]}
这是我的反序列化类
public class SongData2
{
[JsonProperty(PropertyName = "items")]
public List<SongMaders> songs { get; set; }
public class SongMaders
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "artist")]
public string Artist { get; set; }
[JsonProperty(PropertyName = "title")]
public string SongName { get; set; }
[JsonProperty(PropertyName = "url")]
public string SongUri { get; set; }
[JsonProperty(PropertyName = "dutation")]
public int Duration { get; set; }
[JsonProperty(PropertyName = "owner_id")]
public int OwnerId { get; set; }
[JsonProperty(PropertyName = "lyrics_id")]
public int LyricsId { get; set; }
[JsonProperty(PropertyName = "genre_id")]
public int GenreId { get; set; }
}
我需要先获取用户的属性,然后再获取一些自定义类,但它们也无法正常工作。用户属性 - 这是姓名、照片等的位置。 这是我的反序列化代码:
private void Page1_Loaded(object sender, RoutedEventArgs e)
{
WebClient AudioWC = new WebClient();
AudioWC.DownloadStringCompleted += AudioWC_DownloadStringCompleted;
AudioWC.DownloadStringAsync(new Uri(uri));
}
private void AudioWC_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
JObject jobject = JObject.Parse(e.Result);
JArray array = (JArray)jobject["response"]["items"];
MessageBox.Show(array.ToString());
var answer = (SongData2)JsonConvert.DeserializeObject<SongData2>(e.Result);
foreach (SongData2.SongMaders songs in answer.songs)
{
SongData.SongMaders usersongs = new SongData.SongMaders();
usersongs.Artist = songs.Artist;
usersongs.Duration = songs.Duration;
usersongs.SongUri = songs.SongUri;
usersongs.Id = songs.Id;
usersongs.SongName = songs.SongName;
usersongscollforbinding.Add(usersongs);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
this.SpinningAnimation.Stop();
this.AnimEllipse.Visibility = Visibility.Collapsed;
}
UserSongsList.ItemsSource = usersongscollforbinding;
}
希望你能帮助我。你是我最后的希望。
您的 class 表示您的 JSON 结构不正确。请记住,每个 json 对象都需要映射到一个 c# 对象。
这个结构最能代表您的json,您错过了根对象和响应对象。我添加了那些。
public class SongRoot
{
public SongResponse response {get;set;} // maps to { response: { ... }}
}
public class SongResponse {
public int count {get;set;} // maps to count: 529
public List<SongData2> items {get;set;} // maps to items: [{ ... }]
}
public class SongData2
{
public int Id { get; set; } // maps to id: '34',
public string Artist { get; set; } // maps to artist: 'Ocean Jet',
[JsonProperty(PropertyName = "title")]
public string SongName { get; set; }
[JsonProperty(PropertyName = "url")]
public string SongUri { get; set; }
public int Duration { get; set; }
[JsonProperty(PropertyName = "owner_id")]
public int OwnerId { get; set; }
[JsonProperty(PropertyName = "lyrics_id")]
public int LyricsId { get; set; }
[JsonProperty(PropertyName = "genre_id")]
public int GenreId { get; set; }
}
为了序列化您的 JSON 字符串,我使用了以下行:
var root = (SongRoot) JsonConvert.DeserializeObject<SongRoot>(e.Result);
这在 root
中为我提供了 SongRoot
的实例,而 root.response.items
将使您能够访问 4 SongData
classes.
请注意,我必须在您的 JSON 中添加开始 {
和结束 }
,否则它将无效。
这里有几个问题:
您的 json 缺少外括号。如果这不是 copy/paste 错误,您将需要以某种方式解决此问题,例如将
JObject.Parse()
替换为:public static JObject ParseWithMissingBraces(string json) { return JObject.Parse(AddMissingOuterBraces(json)); } public static string AddMissingOuterBraces(string json) { for (int i = 0; i < json.Length; i++) { if (char.IsWhiteSpace(json[i]) || json[i] == '\t' || json[i] == '\r' || json[i] == '\n' || json[i] == '[=10=]') continue; if (json[i] == '[' || json[i] == '{') return json; return string.Format("{{{0}}}", json); } return json; }
字符串文字
'The Raven's Song'
包含未转义的嵌入引号。这看起来是生成 json 的系统错误。它应该是'The Raven\u0027s Song'
或"The Raven's Song"
这可能是因为 json 是用单引号 ('
) 包围的字符串创建的,而 json standard 指定了双引号引用字符 ("
)。我建议您查看此 json 提供者的文档,看看是否有任何方法可以生成正确转义的字符串,因为如果不编写您自己的 json 解析器,则无法在客户端轻松修复此问题.数组
items
实际上看起来是一个多态数组。第一个条目看起来是有关服务用户的信息;随后的条目看起来是关于歌曲的信息。也许这是一个播放列表,第一个条目是播放列表的所有者?无论如何,您需要将用户信息过滤到一个单独的 "bucket" 中,以将其与歌曲信息区分开来。以下 class 层次结构和
JsonConverter
可以解决问题:public abstract class ResponseData { [JsonProperty(PropertyName = "id")] public int Id { get; set; } } public class SongData : ResponseData { [JsonProperty(PropertyName = "artist")] public string Artist { get; set; } [JsonProperty(PropertyName = "title")] public string SongName { get; set; } [JsonProperty(PropertyName = "url")] public string SongUri { get; set; } [JsonProperty(PropertyName = "duration")] public int Duration { get; set; } [JsonProperty(PropertyName = "owner_id")] public int OwnerId { get; set; } [JsonProperty(PropertyName = "lyrics_id")] public int LyricsId { get; set; } [JsonProperty(PropertyName = "genre_id")] public int GenreId { get; set; } } public class UserData : ResponseData { [JsonProperty(PropertyName = "photo")] public string Photo { get; set; } [JsonProperty(PropertyName = "name")] public string Name { get; set; } [JsonProperty(PropertyName = "name_gen")] public string NameGen { get; set; } } public class SongList { [JsonProperty(PropertyName="count")] public int Count { get; set; } [JsonIgnore] public List<SongData> Songs { get; set; } [JsonIgnore] public List<UserData> Users { get; set; } [JsonProperty(PropertyName = "items")] public ResponseData [] Items { get { return (Users ?? Enumerable.Empty<UserData>()).Cast<ResponseData>().Concat((Songs ?? Enumerable.Empty<SongData>()).Cast<ResponseData>()).ToArray(); } set { Songs = (value ?? Enumerable.Empty<ResponseData>()).OfType<SongData>().ToList(); Users = (value ?? Enumerable.Empty<ResponseData>()).OfType<UserData>().ToList(); } } } public class ResponseDataConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(ResponseData).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject item = JObject.Load(reader); if (item["name"] != null) { return item.ToObject<UserData>(); } else { return item.ToObject<SongData>(); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
请注意,为清楚起见,我重命名了您的一些 class 元素和属性,并将嵌套的 class 元素移出了它们的容器。
您的 json 包含一个额外的间接级别,其中包含一个字段
response
:{ response: { } }
这似乎没有增加任何价值,所以您需要从这个包装器中提取有用的数据。
将以上所有内容放在一起,下面从该响应中提取 List<SongData>
和 List<UserData>
假设引用问题已解决:
var json = e.Result;
var jobject = ParseWithMissingBraces(json);
var serializer = new JsonSerializer();
serializer.Converters.Add(new ResponseDataConverter());
var songList = jobject["response"].ToObject<SongList>(serializer);
var songs = songList.Songs;
var users = songList.Users;