无法从Apple的iTunes Genre ID服务中反序列化JSON

时间:2014-10-11 09:10:05

标签: c# json windows-phone-8 windows-8 json.net

Apple的iTunes Genre ID服务返回的JSON与我过去遇到过的其他JSON不同。因此,我无法构建反序列化所需的类。

以下是JSON的一个示例(我为了清楚起见将其剪下来;可以找到完整的JSON here):

{
    "26": {
        "name": "Podcasts",
        "id": "26",
        "url": "https://itunes.apple.com/us/genre/podcasts/id26?mt=2",
        "subgenres": {
            "1301": {
                "name": "Arts",
                "id": "1301",
                "url": "https://itunes.apple.com/us/genre/podcasts-arts/id1301?mt=2",
                "subgenres": {
                    "1306": {
                        "name": "Food",
                        "id": "1306",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-food/id1306?mt=2"
                    },
                    "1401": {
                        "name": "Literature",
                        "id": "1401",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-literature/id1401?mt=2"
                    },
                    "1402": {
                        "name": "Design",
                        "id": "1402",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-design/id1402?mt=2"
                    },
                    "1405": {
                        "name": "Performing Arts",
                        "id": "1405",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-performing-arts/id1405?mt=2"
                    },
                    "1406": {
                        "name": "Visual Arts",
                        "id": "1406",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-visual-arts/id1406?mt=2"
                    },
                    "1459": {
                        "name": "Fashion & Beauty",
                        "id": "1459",
                        "url": "https://itunes.apple.com/us/genre/podcasts-arts-fashion-beauty/id1459?mt=2"
                    }
                }
            },
            "1321": {
                "name": "Business",
                "id": "1321",
                "url": "https://itunes.apple.com/us/genre/podcasts-business/id1321?mt=2",
                "subgenres": {
                    "1410": {
                        "name": "Careers",
                        "id": "1410",
                        "url": "https: //itunes.apple.com/us/genre/podcasts-business-careers/id1410?mt=2"
                    },
                    "1412": {
                        "name": "Investing",
                        "id": "1412",
                        "url": "https: //itunes.apple.com/us/genre/podcasts-business-investing/id1412?mt=2"
                    },
                    "1413": {
                        "name": "Management&Marketing",
                        "id": "1413",
                        "url": "https: //itunes.apple.com/us/genre/podcasts-business-management/id1413?mt=2"
                    },
                    "1471": {
                        "name": "BusinessNews",
                        "id": "1471",
                        "url": "https: //itunes.apple.com/us/genre/podcasts-business-business/id1471?mt=2"
                    },
                    "1472": {
                        "name": "Shopping",
                        "id": "1472",
                        "url": "https: //itunes.apple.com/us/genre/podcasts-business-shopping/id1472?mt=2"
                    }
                }
            }
        }
    }
}

以下是我接收数据的课程:

public class PodcastGenreResult
{
    public PodcastGenreInfo GenreInfo { get; set; }
}

public class PodcastGenreInfo
{
    [JsonProperty("name")]
    public string GenreName { get; set; }
}

这是反序列化调用:

PodcastGenreResult result = JsonConvert.DeserializeObject<PodcastGenreResult>(sResults);

其中sResults是JSON字符串。我已经确认此字符串包含正确的数据。

在此之后,不会抛出任何错误,但result.GenreInfo始终为空。我尝试了其他方法,但这是我觉得最接近的方法。大多数情况下,我使用JsonProperty属性来指定我想要的对象,但我不能在这里因为根名称根据我要求的ID而改变。如何定义我的类以反序列化数据?

2 个答案:

答案 0 :(得分:0)

在我看来问题是设计糟糕的json,使用了类型id而不是属性名称。 json应该是这样的:

{"genre":{"name":"Podcasts","id":"26", ...
    "subgenres":{"genre": {"name":"Arts","id":"1301","url":

而不是:

{"26":{"name":"Podcasts","id":"26", ...
    "subgenres":{"1301":{"name":"Arts","id":"1301","url":

我会将json加载到动态对象中:

dynamic genres = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<dynamic>(json);

如果您希望可以将动态对象转换为强类型对象。

答案 1 :(得分:0)

这实际上很常见。要处理键是动态的对象,您需要反序列化为Dictionary<string, T>,其中T是您的项目类。所以在你的情况下:

Dictionary<string, PodcastGenreInfo> genres = 
    JsonConvert.DeserializeObject<Dictionary<string, PodcastGenreInfo>>(sResults);

另请注意,类型对象的subgenres属性是相同的,因此您也可以将其定义为字典:

public class PodcastGenreInfo
{
    [JsonProperty("name")]
    public string GenreName { get; set; }

    [JsonProperty("subgenres")]
    public Dictionary<string, PodcastGenreInfo> Subgenres { get; set; }
}

这是一个有效的演示:

class Program
{
    static void Main(string[] args)
    {
        using (WebClient client = new WebClient())
        {
            string url = "http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres?id=26";
            string json = client.DownloadString(url);
            var genres = JsonConvert.DeserializeObject<Dictionary<string, PodcastGenreInfo>>(json);
            Dump(new PodcastGenreInfo { GenreName = "Genres", Subgenres = genres }, "");
        }
    }

    private static void Dump(PodcastGenreInfo genre, string indent)
    {
        Console.WriteLine(indent + genre.GenreName);
        if (genre.Subgenres != null)
            foreach (var kvp in genre.Subgenres)
                Dump(kvp.Value, indent + "  ");
    }

    public class PodcastGenreInfo
    {
        [JsonProperty("name")]
        public string GenreName { get; set; }

        [JsonProperty("subgenres")]
        public Dictionary<string, PodcastGenreInfo> Subgenres { get; set; }
    }
}

输出:

Genres
  Podcasts
    Arts
      Design
      Fashion & Beauty
      Food
      Literature
      Performing Arts
      Visual Arts
    Business
      Business News
      Careers
      Investing
      Management & Marketing
      Shopping
    Comedy
    Education
      Educational Technology
      Higher Education
      K-12
      Language Courses
      Training
    Games & Hobbies
      Automotive
      Aviation
      Hobbies
      Other Games
      Video Games
    Government & Organizations
      Local
      National
      Non-Profit
      Regional
    Health
      Alternative Health
      Fitness & Nutrition
      Self-Help
      Sexuality
    Kids & Family
    Music
    News & Politics
    Religion & Spirituality
      Buddhism
      Christianity
      Hinduism
      Islam
      Judaism
      Other
      Spirituality
    Science & Medicine
      Medicine
      Natural Sciences
      Social Sciences
    Society & Culture
      History
      Personal Journals
      Philosophy
      Places & Travel
    Sports & Recreation
      Amateur
      College & High School
      Outdoor
      Professional
    TV & Film
    Technology
      Gadgets
      Podcasting
      Software How-To
      Tech News