大麻烦。又是 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 中添加开始 { 和结束 },否则它将无效。

这里有几个问题:

  1. 您的 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;
    }
    
  2. 字符串文字 'The Raven's Song' 包含未转义的嵌入引号。这看起来是生成 json 的系统错误。它应该是 'The Raven\u0027s Song'"The Raven's Song" 这可能是因为 json 是用单引号 (') 包围的字符串创建的,而 json standard 指定了双引号引用字符 (")。我建议您查看此 json 提供者的文档,看看是否有任何方法可以生成正确转义的字符串,因为如果不编写您自己的 json 解析器,则无法在客户端轻松修复此问题.

  3. 数组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 元素移出了它们的容器。

  4. 您的 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;