С# Проблема с преобразованием из json

Я хочу получать сообщения с тестового сайта с WordPress. Когда я отлаживаю, я вижу, что получаю данные из Интернета, но когда я пытаюсь поместить их в TextBox, они, кажется, не существуют. Я использовал веб-сайт для создания классов из С#, но я думаю, что проблема в моем коде. Я вызываю метод следующим образом:

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; }
           */
    }

}

person Adam Skrášek    schedule 16.02.2017    source источник
comment
когда я пытаюсь поместить их в TextBox, кажется, что они не существуют - можете ли вы показать код, где вы пытаетесь их отобразить?   -  person stuartd    schedule 16.02.2017
comment
textBox1.Text = myPosts.id + - + myPosts.author+ - + myPosts.title;   -  person Adam Skrášek    schedule 16.02.2017


Ответы (1)


Если вы вставите свой 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 представляет собой массив, а не объект. Как поясняется в стандарте JSON:

  • Массив — это упорядоченный набор значений. Массив начинается с [ (левая скобка) и заканчивается ] (правая скобка). Значения разделяются , (запятая).

  • Объект представляет собой неупорядоченный набор пар имя/значение. Объект начинается с { (левая скобка) и заканчивается } (правая скобка).

DataContractJsonSerializer сериализует массивы JSON из и в типы коллекций .Net, такие как 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;
}

Если вы уверены, что ваша служба вернет только один элемент, вы можете вернуть один RootObject, используя Enumerable.SingleOrDefault():

    return list.SingleOrDefault();

Меня немного удивляет, что DataContractJsonSerializer молча ничего не делает в таком случае. json.net создает Unexpected token: StartArray исключение в таких случаях.

Наконец, имя свойства, используемое для заголовка, — "rendered", а не "title". Таким образом, ваш класс Title должен выглядеть так:

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

И чтобы получить доступ к его значению, выполните (добавляя любые нулевые проверки по мере необходимости):

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

(Я не проверял правильность других ваших имен участников контракта данных. Вы должны это сделать, поскольку одно из них было неправильным.)

person dbc    schedule 16.02.2017
comment
Я полностью упустил из виду [], спасибо, что указали на это. Я предполагаю, что мне нужно изменить RootObject myPosts = await Class1.Get(); to List‹RootObject› myPosts = await Class1.Get(); . - person Adam Skrášek; 17.02.2017