C# JSON 对象不会反序列化

Posted

技术标签:

【中文标题】C# JSON 对象不会反序列化【英文标题】:C# JSON Object wont deserialize 【发布时间】:2014-01-28 20:21:41 【问题描述】:

所以我已经能够为一些事情获取 JSON 对象,但是这个对象要复杂得多。

我正在尝试从 Reddit 获取 cmets。 这是我使用的方法:

    public async Task<List<string>> GetComments(string currentSubreddit, string topicID)
    
        string commentUrl = "http://www.reddit.com/r/" + currentSubreddit  + "/comments/" + topicID + "/.json";
        List<Comments> commentList = new List<Comments>();
        string jsonText = await wc.GetJsonText(commentUrl);

        Comments.RootObject deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Comments.RootObject>(jsonText);

        List<string> commentListTest = new List<string>();
        //List<string> commentListTest = deserializeObject.data.children[0].data.children;
        return commentListTest;

    

这是 GetJsonText 方法:

    public async Task<string> GetJsonText(string url)
    
        var request = WebRequest.Create(url);
        string text;
        request.ContentType = "application/json; charset=utf-8";
        var response = (HttpWebResponse)await request.GetResponseAsync();

        using (var sr = new StreamReader(response.GetResponseStream()))
        
            text = sr.ReadToEnd();
        

        return text;
    

这里是对象的链接:http://pastebin.com/WQ8XXGNA 以及指向 jsonText 的链接:http://pastebin.com/7Kh6cA9a

返回的错误是这样的:

“Newtonsoft.Json.JsonSerializationException”类型的异常发生在 mscorlib.dll 中,但未在用户代码中处理

附加信息:无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'JuicyReddit.Comments+RootObject',因为该类型需要 JSON 对象(例如 "name":"value")正确反序列化。

如果有人能帮助我找出问题所在,我将不胜感激。 谢谢

【问题讨论】:

你从哪里得到这个 json 数据?认为您发布的 json 字符串无效。 @Jim 我得到这个 url 并在 GetJsonText www.reddit.com/r/AskReddit/cmets/1u​​t6xc/.json 中使用它 这里解释了额外的错误***.com/questions/17762032/… @Jim 你知道如何在我使用 Newtonsoft 的情况下做到这一点吗?仍然不确定如何解决它。 我为你添加了示例代码 【参考方案1】:

实际上你的代码有一些问题

 public async Task<List<string>> GetComments(string currentSubreddit, string topicID)

这里你不需要返回一个字符串列表,你需要返回一个完整的对象

首先将模型中的 RootObject 重命名为适当的名称,例如“CommentsObject”

所以像这样设置你的类并将其命名为 CommentsObject.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YOURNAMESPACE.Comments

    public class MediaEmbed
    
    

    public class SecureMediaEmbed
    
    

    public class Data4
    
        public int count  get; set; 
        public string parent_id  get; set; 
        public List<string> children  get; set; 
        public string name  get; set; 
        public string id  get; set; 
        public string subreddit_id  get; set; 
        public object banned_by  get; set; 
        public string subreddit  get; set; 
        public object likes  get; set; 
        public object replies  get; set; 
        public bool? saved  get; set; 
        public int? gilded  get; set; 
        public string author  get; set; 
        public object approved_by  get; set; 
        public string body  get; set; 
        public object edited  get; set; 
        public object author_flair_css_class  get; set; 
        public int? downs  get; set; 
        public string body_html  get; set; 
        public string link_id  get; set; 
        public bool? score_hidden  get; set; 
        public double? created  get; set; 
        public object author_flair_text  get; set; 
        public double? created_utc  get; set; 
        public object distinguished  get; set; 
        public object num_reports  get; set; 
        public int? ups  get; set; 
    

    public class Child2
    
        public string kind  get; set; 
        public Data4 data  get; set; 
    

    public class Data3
    
        public string modhash  get; set; 
        public List<Child2> children  get; set; 
        public object after  get; set; 
        public object before  get; set; 
    

    public class Replies
    
        public string kind  get; set; 
        public Data3 data  get; set; 
    

    public class Data2
    
        public string domain  get; set; 
        public object banned_by  get; set; 
        public MediaEmbed media_embed  get; set; 
        public string subreddit  get; set; 
        public object selftext_html  get; set; 
        public string selftext  get; set; 
        public object likes  get; set; 
        public object secure_media  get; set; 
        public object link_flair_text  get; set; 
        public string id  get; set; 
        public SecureMediaEmbed secure_media_embed  get; set; 
        public bool clicked  get; set; 
        public bool stickied  get; set; 
        public string author  get; set; 
        public object media  get; set; 
        public int score  get; set; 
        public object approved_by  get; set; 
        public bool over_18  get; set; 
        public bool hidden  get; set; 
        public string thumbnail  get; set; 
        public string subreddit_id  get; set; 
        public object edited  get; set; 
        public object link_flair_css_class  get; set; 
        public object author_flair_css_class  get; set; 
        public int downs  get; set; 
        public bool saved  get; set; 
        public bool is_self  get; set; 
        public string permalink  get; set; 
        public string name  get; set; 
        public double created  get; set; 
        public string url  get; set; 
        public object author_flair_text  get; set; 
        public string title  get; set; 
        public double created_utc  get; set; 
        public int ups  get; set; 
        public int num_comments  get; set; 
        public bool visited  get; set; 
        public object num_reports  get; set; 
        public object distinguished  get; set; 
        public Replies replies  get; set; 
        public int? gilded  get; set; 
        public string parent_id  get; set; 
        public string body  get; set; 
        public string body_html  get; set; 
        public string link_id  get; set; 
        public bool? score_hidden  get; set; 
        public int? count  get; set; 
        public List<string> children  get; set; 
    

    public class Child
    
        public string kind  get; set; 
        public Data2 data  get; set; 
    

    public class Data
    
        public string modhash  get; set; 
        public List<Child> children  get; set; 
        public object after  get; set; 
        public object before  get; set; 
    

    public class CommentsObject
    
        public string kind  get; set; 
        public Data data  get; set; 
    

让你的命名空间正确!

然后处理请求并反序列化为commentobjects列表:(如果你愿意,你可以使用webclient而不是httpclient,这只是一个例子)

    private HttpClient client;

    public async Task<List<CommentsObject>> GetComments()
    
        client = new HttpClient();
        var response = await client.GetAsync("http://www.reddit.com/r/AskReddit/comments/1ut6xc.json");
        if (response.IsSuccessStatusCode)
        
            string json = await response.Content.ReadAsStringAsync();
            List<CommentsObject> comments = await JsonConvert.DeserializeObjectAsync<List<CommentsObject>>(json);
            return comments;
        
        else
        
            throw new Exception("Errorhandling message");
        
    

【讨论】:

感谢您的深入回应,非常感谢。我带来的一个错误是命名空间。当我尝试为 GetComments() 方法执行 时,它说命名空间被用作类型 Getcmets() 是服务类或表单后端代码中的一种方法 我明白了。这就是我的方法的类型: public async Task> GetComments(string url) 应该可以吗?因为我没有从中得到cmets。您介意开始聊天以获取快速帮助吗? 实际上我认为我有它的工作。遍历此并将 cmets 添加到列表视图的最佳方法是什么?因为当我把列表拿回来时,里面总是有 2 个元素,我只是确定我应该做什么 我想那将是一个不同的主题:),但是在这种情况下,你会得到 2 个数组,你需要深入挖掘并迭代以获得 cmets【参考方案2】:

这并不理想(也不是完全的答案,而是更多的解决方法),但我创建了模拟 reddit 响应 json 的模型,以使反序列化超级容易。我在模型属性上使用 JsonProperty 属性来美化模型。

Here are the models

由于我的模型直接模拟了 json,我可以使用 json.net 的通用反序列化方法。

【讨论】:

我将如何使用 Newtonsoft 插件。有点困惑它是如何工作的 S: 假设我执行了对 reddit.com/r/all.json 的访问,Reddit 为您提供了一个“列表”。我用ListingModel 模拟了listing json。要获得强类型的ListingModel,我所要做的就是: var listing = JsonConvert.DeserializeObject(response) 其中 response 是 json。由于 ListingModel 及其子代模拟了返回的 json,它只是将 json 中的属性名称与我的模型匹配。如果您想了解它是如何使用的,请查看该 repo 中的测试控制台项目。 感谢您的回复。我会看看你在说什么,并尝试让它发挥作用:)

以上是关于C# JSON 对象不会反序列化的主要内容,如果未能解决你的问题,请参考以下文章

C# JSON 反序列化

将 json 反序列化到我的 C# 对象中会出错

C# - 反序列化具有多个对象的 Json 对象

在 C# 中反序列化复杂对象

将 JSON 字符串反序列化为多个 C# 对象

C#序列化及反序列化Json对象通用类JsonHelper