десериализовать ответ API с помощью newtonsoft - PullRequest
2 голосов
/ 05 марта 2020

Мне нужна помощь в десериализации ответа. (Я звоню на Data247 по номеру телефона, и API возвращает оператора мобильной связи). Вызов API работает, и я получаю верный ответ, который выглядит следующим образом:

{
    "response": {
        "status": "OK",
        "results": [
            {
                "phone": "11234567890",
                "wless": "y",
                "carrier_name": "Blue Licenses Holding, LLC",
                "carrier_id": 6,
                "sms_address": "1234567890@txt.att.net",
                "mms_address": "1234567890@mms.att.net"
            }
        ]
    }
}

Это приложение C#. NET winforms. Чтобы проверить это, вам понадобится ключ доступа от Data247. Все работает через вызов API. Моя проблема с этой строкой:

Data247 data247 = JsonConvert.DeserializeObject<Data247>(response.Content);

... и поэтому я не думаю, что мой класс структурирован правильно. ... или, может быть, я не правильно десериализирую. Мой код выглядит так:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;

using RestSharp;
using Newtonsoft.Json;

namespace myTest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void btnVerify_Click(object sender, EventArgs e)
        {
            try
            {
                string request = txtEndpoint.Text;
                request += "?key=" + txtAccessKey.Text;
                request += "&api=CU";
                request += "&phone=" + txtPhone.Text;
                var client = new RestClient(request);
                var response = client.Execute(new RestRequest());
                Data247 data247 = JsonConvert.DeserializeObject<Data247>(response.Content);

                MessageBox.Show(response.Content);
                Debug.Print(response.Content);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.ToString());
            }
        }

        public class Data247
        {
            Response response { get; set; }
            public class Response
            {
                public string status { get; set; }
                Results results { get; set; }

                public class Results
                {
                    List<Phone> phones = new List<Phone>();
                    public Phone phone { get; set; }
                    public class Phone
                    {
                        public string phone { get; set; }
                        public string wless { get; set; }
                        public string carrier_name { get; set; }
                        public string carrier_id { get; set; }
                        public string sms_address { get; set; }
                        public string mms_address { get; set; }
                    }
                }
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Помимо рекомендованного трюка от @Hirasawa, я считаю, что важно понимать, как все это работает, поэтому я хотел бы отметить пару глюков в вашем коде.

Вам не нужен класс Phone.

Если вы посмотрите на структуру данных, номер телефона является только свойством элемента результата. Кроме того, Results является массивом, поэтому давайте обновим код, чтобы исправить эти ошибки:

public class Data247
{
    Response response { get; set; }

    public class Response
    {
        public string status { get; set; }

        public Results[] results { get; set; }

        public class Results
        {
            public string phone { get; set; }
            public string wless { get; set; }
            public string carrier_name { get; set; }
            public string carrier_id { get; set; }
            public string sms_address { get; set; }
            public string mms_address { get; set; }
        }
    }
}

Целевые свойства должны быть опубликованы c.

В чтобы правильно десериализовать ответ, свойства в ваших целевых классах должны быть publi c. Исправляя эти ошибки, мы получаем:

public class Data247
{
    public Response response { get; set; }

    public class Response
    {
        public string status { get; set; }

        public Results[] results { get; set; }

        public class Results
        {
            public string phone { get; set; }
            public string wless { get; set; }
            public string carrier_name { get; set; }
            public string carrier_id { get; set; }
            public string sms_address { get; set; }
            public string mms_address { get; set; }
        }
    }
}

С учетом вышеуказанных изменений код теперь работает. Ну, почти ;-). Получается, что теперь у нас есть вложенный класс Results на том же уровне свойства с именем Results. Это недопустимо в C#, и компилятор сообщит вам об этом с ошибкой: «Элемент Results уже объявлен.» .

Исправить несложно, мы просто перемещаем вложенные классы во внешнюю область видимости или можем переименовать классы Response и Results во что-то вроде ResponseDTO и ResultDTO, но я нахожу бывший проще сделать. Итак, теперь наш код:

public class Data247
{
    public Response response { get; set; }
}

public class Response
{
    public string status { get; set; }

    public Results[] results { get; set; }
}

public class Results
{
    public string phone { get; set; }
    public string wless { get; set; }
    public string carrier_name { get; set; }
    public string carrier_id { get; set; }
    public string sms_address { get; set; }
    public string mms_address { get; set; }
}

БОНУС: Напишите код idiomati c C#.

Если вы хотите написать код idiomati c, Вы должны использовать рекомендуемые имена свойств. Это вопрос стиля и кода, как он работает, но C# разработчик поблагодарит вас, если ваш код написан правильно.

Это краткое резюме того, что я сделаю:

  1. Переименование имен свойств в UpperCamelCase формате. Например: mms_address должно быть MmsAddress.
  2. . Из-за 1. мы также должны использовать атрибуты для сопоставления фактических имен свойств в json с именем свойства C#.

Ниже приведен окончательный код:

public class Data247
{
    [JsonProperty("Response")]
    public Response Response { get; set; }
}

public class Response
{
    [JsonProperty("status")]
    public string Status { get; set; }

    [JsonProperty("results")]
    public Results[] Results { get; set; }
}

public class Results
{
    [JsonProperty("Phone")]
    public string Phone { get; set; }

    [JsonProperty("wless")]
    public string Wless { get; set; }

    [JsonProperty("carrier_name")]
    public string CarrierName { get; set; }

    [JsonProperty("carrier_id")]
    public string CarrierId { get; set; }

    [JsonProperty("sms_address")]
    public string SmsAddress { get; set; }

    [JsonProperty("mms_address")]
    public string MmsAddress { get; set; }
}

Надеюсь, это поможет!

0 голосов
/ 05 марта 2020

https://dailydotnettips.com/did-you-know-you-can-automatically-create-classes-from-json-or-xml-in-visual-studio/ И вот как вы получаете (в основном) правильный класс для любой json структуры.

...