Десериализация объекта полученного со стороннего сервера
Есть сторонний сервер с API, которое описывается следующим образом:
Структура запроса
Для получения данных об отсканированных талонах необходимо выполнить POST запрос со следующими параметрами (пример cURL):
curl --location --request POST 'https://xxxxx/app/api/barcodes/get.php' \
--header 'Application: remoteData' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=ваш_токен' \
--data-urlencode 'date=2021-08-18 10:00:00'
- Адрес обращения:
https://xxxxxx/app/api/barcodes/get.php - Обязательный заголовок:
Application: remoteData - Поля запроса:
token– ваш уникальный идентификаторdate– дата и время, после которого будут собраны данные в форматеYYYY-MM-DD HH:II:SS
Структура ответа сервера
При успешной обработке ответ сервера будет представлен в следующем виде:
{
"status": "OK",
"error": "",
"region": 76,
"date": "2021-08-11 10:00:00",
"items": {
"2": "2021-08-17 16:26:32",
"3": "2021-08-17 16:28:48",
"12": "2021-08-17 19:30:19"
}
}
Пример ответа сервера при возникновении ошибки. Например, указан неправильный токен пользователя:
{
"status": 0,
"error": "Ошибочный токен пользователя",
"region": "",
"date": "2021-08-11 10:00:00",
"items": []
}
В итоге строка ответа при ошибке выглядит следующим образом:
"{\"status\":103,\"error\":\"Не найден токен\",\"region\":\"\",\"date\":\"\",\"items\":[]}"
Для сериализации запроса и десериализации ответа создал следующие классы:
public class RequestMessageData
{
public string token { get; set; }
public string date { get; set; }
}
public class ResponseMessageDataQRCode
{
public string status { get; set; }
public string error { get; set; }
public int region { get; set; }
public string date { get; set; }
public Items [] items { get; set; }
}
public class Items
{
public string name { get; set; }
public string dateTime { get; set; }
}
Отправляю запрос и обрабатываю ответ следующим образом:
string jsonRequest = JsonSerializer.Serialize(requestMessage);
string jsonResponseData = await PostRequesHttpAsync(url, jsonRequest);
responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCode>(jsonResponseData);
На строке responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCode> получаю ошибку десериализации.
Полный текст метода:
[HttpPost]
[Route("requestqrcodesreceiving")]
public async Task<IActionResult> RequestQRcodesReceiving([FromBody] string dateTimeStr)
{
string url = "https://хххххх/app/api/barcodes/get.php";
ReportQrCodeExchange reportQrCodeExchange = new ReportQrCodeExchange();
ResponseMessageDataQRCode responseData = null;
string dateTimeNow = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
RequestMessageData requestMessage = new RequestMessageData
{
token = "N2U1OThkZDZkZDliZGFiM/lAfhoRNk0D+iJh2Z1h1fpYEUWXkzsbvGg1",
date = dateTimeNow
};
try
{
string jsonRequest = JsonSerializer.Serialize(requestMessage);
string jsonResponseData = await PostRequesHttpAsync(url, jsonRequest);
responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCode>(jsonResponseData);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
if (responseData != null)
{
if (responseData.status.Equals("200") || responseData.status.Equals("OK"))
{
reportQrCodeExchange = CheckQrCodes(responseData);
}
else
{
reportQrCodeExchange.error = responseData.error;
reportQrCodeExchange.status = responseData.status;
return Ok(reportQrCodeExchange);
}
}
return Ok(reportQrCodeExchange);
}
Метод формирования запроса:
public async Task<string> PostRequesHttpAsync(string url, string json)
{
using HttpContent content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded");
httpClient.DefaultRequestHeaders.Add("Application", "remoteData");
//httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
using HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
Ответы (1 шт):
Во-первых, запрос вы отправляете неверно. Надо как form-urlencoded, а вы как json.
private async Task<string> PostFormAsync(string url, IEnumerable<KeyValuePair<string, string>> data)
{
using var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new FormUrlEncodedContent(data)
};
request.Headers.Add("Application", "remoteData");
using var response = await httpClient.SendAsync(request).ConfigureAwait(false);
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
Ну и чтобы это использовать, я не много изменил код
[HttpPost]
[Route("requestqrcodesreceiving")]
public async Task<IActionResult> RequestQRcodesReceiving([FromBody] string dateTimeStr)
{
string url = "https://хххххх/app/api/barcodes/get.php";
ReportQrCodeExchange reportQrCodeExchange = new ReportQrCodeExchange();
ResponseMessageDataQRCode responseData = null;
string dateTimeNow = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
Dictionary<string, string> requestMessage = new Dictionary<string, string>
{
["token"] = "N2U1OThkZDZkZDliZGFiM/lAfhoRNk0D+iJh2Z1h1fpYEUWXkzsbvGg1",
["date"] = dateTimeNow
};
try
{
string jsonResponseData = await PostFormAsync(url, requestMessage);
responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCode>(jsonResponseData);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
if (responseData != null)
{
if (responseData.status.Equals("200") || responseData.status.Equals("OK"))
{
reportQrCodeExchange = CheckQrCodes(responseData);
}
else
{
reportQrCodeExchange.error = responseData.error;
reportQrCodeExchange.status = responseData.status;
return Ok(reportQrCodeExchange);
}
}
return Ok(reportQrCodeExchange);
}
Во-вторых, Items не нужен, принятые данные можно десереализовать в словать.
public class ResponseMessageDataQRCode
{
public string status { get; set; }
public string error { get; set; }
public int region { get; set; }
public DateTime date { get; set; }
public Dictionary<string, DateTime> items { get; set; }
}
Кстати, получается что класс RequestMessageData тоже не нужен.