从 json 转换的 C# 问题

C# Issue with converting from json

我想从 WordPress 测试站点获取帖子。当我调试时,我可以看到我从 Web 获取数据,但是当我尝试将它们放入 TextBox 时,它们似乎不存在。我使用网站从 C# 创建 类,但我认为问题出在我的代码中。我这样调用方法:

RootObject myPosts = await Class1.Get();

然后,为了向用户显示值,我这样做:

textBox1.Text = myPosts.id + " - " + myPosts.author+ "-" + myPosts.title;

代码:

public class Class1
{
    public async static Task<RootObject> Get()
    {
         var http = new HttpClient();
        var response = await http.GetAsync("http://bearlike-attackers.000webhostapp.com/wp-json/wp/v2/posts?search=TEST");
        var result = await response.Content.ReadAsStringAsync();
        var serializer = new DataContractJsonSerializer(typeof(RootObject));

        var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
        var data = (RootObject)serializer.ReadObject(ms);
        return data;
    }
}
    [DataContract]
    public class Guid
    {
        [DataMember]
        public string rendered { get; set; }
    }
    [DataContract]
    public class Title
    {
        [DataMember]
        public string title { get; set; }
    }
    [DataContract]
    public class Content
    {
        [DataMember]
        public string rendered { get; set; }

        [DataMember]
        public bool @protected { get; set; }
    }
    [DataContract]
    public class Excerpt
    {
        [DataMember]
        public string rendered { get; set; }

        [DataMember]
        public bool @protected { get; set; }
    }
    [DataContract]
    public class Self
    {
        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class Collection
    {
        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class About
    {
        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class Author
    {
        [DataMember]
        public bool embeddable { get; set; }

        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class Reply
    {
        [DataMember]
        public bool embeddable { get; set; }

        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class VersionHistory
    {
        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class WpAttachment
    {
        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class WpTerm
    {
        [DataMember]
        public string taxonomy { get; set; }

        [DataMember]
        public bool embeddable { get; set; }

        [DataMember]
        public string href { get; set; }
    }
    [DataContract]
    public class Cury
    {
        [DataMember]
        public string name { get; set; }

        [DataMember]
        public string href { get; set; }

        [DataMember]
        public bool templated { get; set; }
    }
    /*
    public class Links
    {
        public List<Self> self { get; set; }
        public List<Collection> collection { get; set; }
        public List<About> about { get; set; }
        public List<Author> author { get; set; }
        public List<Reply> replies { get; set; }
        public List<VersionHistory> __invalid_name__version-history { get; set; }
    public List<WpAttachment> __invalid_name__wp:attachment { get; set; }
public List<WpTerm> __invalid_name__wp:term { get; set; }
    public List<Cury> curies { get; set; }
}
*/
    [DataContract]
    public class RootObject
    {
        [DataMember]
        public string date { get; set; }

        [DataMember]
        public int id { get; set; }

        [DataMember]
        public string date_gmt { get; set; }

        [DataMember]
        public Guid guid { get; set; }

        [DataMember]
        public string modified { get; set; }

        [DataMember]
        public string modified_gmt { get; set; }

        [DataMember]
        public string slug { get; set; }

        [DataMember]
        public string type { get; set; }

        [DataMember]
        public string link { get; set; }

        [DataMember]
        public Title title { get; set; }

        [DataMember]
        public Content content { get; set; }

        [DataMember]
        public Excerpt excerpt { get; set; }

        [DataMember]
        public int author { get; set; }

        [DataMember]
        public int featured_media { get; set; }

        [DataMember]
        public string comment_status { get; set; }

        [DataMember]
        public string ping_status { get; set; }

        [DataMember]
        public bool sticky { get; set; }

        [DataMember]
        public string template { get; set; }

        [DataMember]
        public string format { get; set; }
        /*
            [DataMember]
            public List<object> meta { get; set; }

            [DataMember]
            public List<int> categories { get; set; }

            [DataMember]
            public List<object> tags { get; set; }


            [DataMember]
           public Links _links { get; set; }
           */
    }

}

如果您将 URL 粘贴到 http://jsonlint.com/,您将看到格式化后的 JSON 如下所示:

[{
    "id": 4,
    "date": "2017-02-16T14:28:41",
    "date_gmt": "2017-02-16T13:28:41",
    "guid": {
        "rendered": "https:\/\/bearlike-attackers.000webhostapp.com\/?p=4"
    },
    "modified": "2017-02-16T14:28:41",
    "modified_gmt": "2017-02-16T13:28:41",
    "slug": "testy",
    "type": "post",
    "link": "https:\/\/bearlike-attackers.000webhostapp.com\/2017\/02\/16\/testy\/",
    "title": {
        "rendered": "Testy"
    },
// And many other properties.

}]

注意到外面的 [] 了吗?您的问题是您的外部 JSON 容器是一个数组,而不是 object。如 JSON standard 中所述:

  • 数组是有序的 collection 值。数组以 [(左括号)开始,以 ](右括号)结束。值由 ,(逗号)分隔。

  • object 是 name/value 对的无序集合。 object 以 {(左大括号)开始,以 }(右大括号)结束。

DataContractJsonSerializer 将 JSON 数组序列化为 .Net collection 类型,例如 List<T>T []。因此,您必须按如下方式反序列化:

public async static Task<List<RootObject>> Get()
{
    var http = new HttpClient();
    var response = await http.GetAsync("http://bearlike-attackers.000webhostapp.com/wp-json/wp/v2/posts?search=TEST");
    var result = await response.Content.ReadAsStringAsync();

    var serializer = new DataContractJsonSerializer(typeof(List<RootObject>));
    var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
    var list = (List<RootObject>)serializer.ReadObject(ms);
    return list;
}

如果您确定您的服务只会 return 一项,您可以使用 Enumerable.SingleOrDefault():

return 一项 RootObject
    return list.SingleOrDefault();

让我有点惊讶的是DataContractJsonSerializer在这种情况下默默地什么都不做。 throws an Unexpected token: StartArray 这种情况例外。

最后,用于标题的 属性 名称是 "rendered" 而不是 "title"。因此你的 Title class 需要看起来像:

[DataContract]
public class Title
{
    [DataMember]
    public string rendered { get; set; }
}

要访问它的值,请执行(根据需要添加任何空检查):

var s = myPost.id + " - " + myPost.author + "-" + myPost.title.rendered;

(我还没有检查你的其他数据合同成员名称的正确性。你应该检查,因为有一个不正确。)