将由对象列表组成的JSON响应反序列化为C#类

3

我正在使用NewsBlur API进行开发,它返回一个订阅源列表。响应的JSON类型为:

{
    "authenticated": true,
    "user": "sathyabhat",
    "feeds": {},
    "flat_folders": { },
    result: "ok"
}

其中feeds:的类型为

    "feeds": {
        "96705": {
            "feed_address": "http://www.linuxhaxor.net/",
            "updated": "8492 hours",
            "favicon_text_color": null,
            "subs": 35,
            "feed_link": "http://www.linuxhaxor.net/",
            "favicon_fetching": true,
            "nt": 0,
            "updated_seconds_ago": 30573336,
            "num_subscribers": 35,
            "feed_title": "LinuxHaxor.net",
            "favicon_fade": null,
            "exception_type": "feed",
            "exception_code": 503,
            "favicon_color": null,
            "active": true,
            "ng": 0,
            "feed_opens": 0,
            "id": 96705,
            "ps": 0,
            "has_exception": true
        },
        "768840": {
            "feed_address": "http://feeds.feedburner.com/PathikShahDotCom",
            "updated": "3 hours",
            "favicon_text_color": "black",
            "subs": 1,
            "feed_link": "http://www.pathikshah.com/blog",
            "favicon_fetching": false,
            "nt": 0,
            "updated_seconds_ago": 13043,
            "num_subscribers": 1,
            "feed_title": "Pathik Shah",
            "favicon_fade": "769456",
            "favicon_color": "b2d092",
            "active": true,
            "ng": 0,
            "feed_opens": 0,
            "id": 768840,
            "ps": 0
        },
        "768842": {
            "feed_address": "http://feeds.preshit.net/preshit/blog",
            "updated": "3 hours",
            "favicon_text_color": null,
            "subs": 1,
            "feed_link": "http://preshit.net",
            "favicon_fetching": false,
            "nt": 3,
            "updated_seconds_ago": 13536,
            "num_subscribers": 1,
            "feed_title": "Preshit Deorukhkar",
            "favicon_fade": null,
            "favicon_color": null,
            "active": true,
            "ng": 0,
            "feed_opens": 1,
            "id": 768842,
            "ps": 0
        },
        "768843": {
            "feed_address": "http://quizwith.net/feed/",
            "updated": "3 hours",
            "favicon_text_color": "white",
            "subs": 1,
            "feed_link": "http://quizwith.net",
            "favicon_fetching": false,
            "nt": 0,
            "updated_seconds_ago": 11617,
            "num_subscribers": 1,
            "feed_title": "quizwith.net",
            "favicon_fade": "c22900",
            "favicon_color": "fe6501",
            "active": true,
            "ng": 0,
            "feed_opens": 0,
            "id": 768843,
            "ps": 0
        }

[...等等...]

    }

基本上,这是一个订阅对象列表。现在,我正在尝试使用 JSON.net 将其反序列化为C#对象,但我的类成员被填充为null值。
我的类是基于我收到的响应建模的:
 public class FeedResponse
    {
   public string authenticated { get; set; }
   public string user { get; set; }
   public List<feed> feeds { get; set; }
   public string flat_folders { get; set; }
   public string result { get; set; }
}

public class feed
{
    public string feed_address { get; set; }
    public string updated { get; set; }
    public string favicon_text_color { get; set; }
    public int subs { get; set; }
    public string feed_link { get; set; }
    public bool favicon_fetching { get; set; }
    public string nt { get; set; }
    public string updated_seconds_ago { get; set; }
    public int num_subscribers { get; set; }
    public string feed_title { get; set; }
    public string favicon_fade { get; set; }
    public string exception_type { get; set; }
    public string exception_code { get; set; }
    public string favicon_color { get; set; }
    public bool active { get; set; }
    public string ng { get; set; }
    public int feed_opens { get; set; }
    public int id { get; set; }
    public bool has_exception { get; set; }

}

这是尝试反序列化(使用RestSharp)的代码行:
 return Execute<FeedResponse>(request);

显然,在尝试解析反馈响应的JSON时出现了问题。
有什么指点,告诉我我做错了什么吗?

你尝试将其反序列化为字典了吗? - Daniel A. White
@DanielA.White - 我不确定字典如何适配这些数据? - Sathyajith Bhat
你尝试过通过代码构建FeedCollection并进行序列化以查看差异吗? - Joseph Le Brech
@Sathya 如果你周六早上还没有收到这个消息,请在Skype上告诉我。 - jcolebrand
3个回答

5

Feeds是一个字典(Dictionary),键(Keys)的类型是int,值(Value)的类型是Feed,而不是列表(List)。

编辑:更多细节,JSON格式的对象列表如下:

[{ name: 'elem1'},
{ name: 'elem2'},
{ name: 'elem3'}]

编辑2:完整的样例代码如下:

 using System; 
 using System.Collections.Generic; 
 using System.Linq;
 using System.Web.Script.Serialization;

 namespace JSON {
     class Program
     {
         static void Main(string[] args)
         {
             var json = @"{
     ""authenticated"": true,
     ""user"": ""sathyabhat"",
     ""feeds"": {
         ""96705"": {
             ""feed_address"": ""http://www.linuxhaxor.net/"",
             ""updated"": ""8492 hours"",
             ""favicon_text_color"": null,
             ""subs"": 35,
             ""feed_link"": ""http://www.linuxhaxor.net/"",
             ""favicon_fetching"": true,
             ""nt"": 0,
             ""updated_seconds_ago"": 30573336,
             ""num_subscribers"": 35,
             ""feed_title"": ""LinuxHaxor.net"",
             ""favicon_fade"": null,
             ""exception_type"": ""feed"",
             ""exception_code"": 503,
             ""favicon_color"": null,
             ""active"": true,
             ""ng"": 0,
             ""feed_opens"": 0,
             ""id"": 96705,
             ""ps"": 0,
             ""has_exception"": true
         },
         ""768840"": {
             ""feed_address"": ""http://feeds.feedburner.com/PathikShahDotCom"",
             ""updated"": ""3 hours"",
             ""favicon_text_color"": ""black"",
             ""subs"": 1,
             ""feed_link"": ""http://www.pathikshah.com/blog"",
             ""favicon_fetching"": false,
             ""nt"": 0,
             ""updated_seconds_ago"": 13043,
             ""num_subscribers"": 1,
             ""feed_title"": ""Pathik Shah"",
             ""favicon_fade"": ""769456"",
             ""favicon_color"": ""b2d092"",
             ""active"": true,
             ""ng"": 0,
             ""feed_opens"": 0,
             ""id"": 768840,
             ""ps"": 0
         },
         ""768842"": {
             ""feed_address"": ""http://feeds.preshit.net/preshit/blog"",
             ""updated"": ""3 hours"",
             ""favicon_text_color"": null,
             ""subs"": 1,
             ""feed_link"": ""http://preshit.net"",
             ""favicon_fetching"": false,
             ""nt"": 3,
             ""updated_seconds_ago"": 13536,
             ""num_subscribers"": 1,
             ""feed_title"": ""Preshit Deorukhkar"",
             ""favicon_fade"": null,
             ""favicon_color"": null,
             ""active"": true,
             ""ng"": 0,
             ""feed_opens"": 1,
             ""id"": 768842,
             ""ps"": 0
         },
         ""768843"": {
             ""feed_address"": ""http://quizwith.net/feed/"",
             ""updated"": ""3 hours"",
             ""favicon_text_color"": ""white"",
             ""subs"": 1,
             ""feed_link"": ""http://quizwith.net"",
             ""favicon_fetching"": false,
             ""nt"": 0,
             ""updated_seconds_ago"": 11617,
             ""num_subscribers"": 1,
             ""feed_title"": ""quizwith.net"",
             ""favicon_fade"": ""c22900"",
             ""favicon_color"": ""fe6501"",
             ""active"": true,
             ""ng"": 0,
             ""feed_opens"": 0,
             ""id"": 768843,
             ""ps"": 0
         }
     },
     ""flat_folders"": { },
     result: ""ok"" }";

             var jsonSerializer = new JavaScriptSerializer();
             var response = jsonSerializer.Deserialize<FeedResponse(json);
             Console.Write(jsonSerializer.Serialize(response));
             Console.ReadKey();
         }
     }

     public class FeedResponse
     {
         public bool authenticated { get; set; }
         public string user { get; set; }
         public Dictionary<string,feed> feeds { get; set; }
         public object flat_folders { get; set; }
         public string result { get; set; }
     }

     public class feed
     {
         public string feed_address { get; set; }
         public string updated { get; set; }
         public string favicon_text_color { get; set; }
         public int subs { get; set; }
         public string feed_link { get; set; }
         public bool favicon_fetching { get; set; }
         public string nt { get; set; }
         public string updated_seconds_ago { get; set; }
         public int num_subscribers { get; set; }
         public string feed_title { get; set; }
         public string favicon_fade { get; set; }
         public string exception_type { get; set; }
         public string exception_code { get; set; }
         public string favicon_color { get; set; }
         public bool active { get; set; }
         public string ng { get; set; }
         public int feed_opens { get; set; }
         public int id { get; set; }
         public bool has_exception { get; set; }
     } }

您需要其他信息来完善答案吗? - Guillaume86
不,这非常好地回答了我的问题,谢谢! - Sathyajith Bhat
哎呀,我忘了。谢谢你提醒我!@Guillaume86 - Sathyajith Bhat

1

使用JsonReader,使用Json.Net,您的示例应该如下所示:

public class Feeds
{
    public bool authenticated;
    public string user;
    public Dictionary<string, Feed> feeds;


    public void ReadJson(JsonReader reader)
    {
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndObject)
                break;

            if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "authenticated")
            {
                reader.Read();
                authenticated = (bool)reader.Value;
            }
            else if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "user")
            {
                reader.Read();
                user = (string)reader.Value;
            }
            else if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "feeds")
            {
                feeds = new Dictionary<string, Feed>();
                while (reader.Read())
                {
                    if (reader.TokenType == JsonToken.EndObject)
                        break;

                    if (reader.TokenType == JsonToken.PropertyName)
                    {
                        string key = (string)reader.Value;
                        feeds.Add(key, Feed.ReadFromJson(reader));
                    }
                }

            }
        }
    }

    public static Feeds ReadFromJson(Stream stream)
    {
        using (StreamReader sr = new StreamReader(stream))
        {
            using (Newtonsoft.Json.JsonReader jsonReader = new Newtonsoft.Json.JsonTextReader(sr))
            {
                Feeds feeds = new Feeds();
                feeds.ReadJson(jsonReader);
                return feeds;
            }
        }
    }
}

public class Feed
{
    public string feed_address;
    public string updated;

    public void ReadJson(JsonReader reader)
    {
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndObject)
                break;

            if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "feed_address")
            {
                reader.Read();
                feed_address = (string)reader.Value;
            }
            else if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "updated")
            {
                reader.Read();
                updated = (string)reader.Value;
            }
        }
    }

    public static Feed ReadFromJson(JsonReader reader)
    {
        Feed feed = new Feed();
        feed.ReadJson(reader);
        return feed;
    }
}

1

由于您返回的Json字符串包含像96705,768840,768842,768843这样的名称,这些名称不是有效的c#变量名称,因此,除非您使用feeds的字典,否则无法将字符串反序列化为类。因此,如果访问对象的某些属性作为dict["key"]是不可避免的,那么为什么还要声明类FeedResponsefeed呢?只需使用Json.Net的JObjectJTokenJProperty即可。

JObject rootObj =  JsonConvert.DeserializeObject(jstr) as JObject;
Console.WriteLine(
    "Authenticated:" + rootObj["authenticated"] + 
    " USER:"         + rootObj["user"] + 
    " RESULT:"       + rootObj["result"]);


foreach (JProperty feed in rootObj["feeds"])
{
    Console.WriteLine(feed.Name + " " +  feed.Value["feed_address"]);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接