#c# #json
#c# #json
Вопрос:
Я пытаюсь десериализовать ответ потока JSON из ВЕБ-API в объект C #. Вызов
(code before)
return DeserializeJsonFromStream<DistanceMatrixObject>(stream)
Потоковый ответ JSON
[ {
"id" : "904506056107888640",
"type" : "SENT",
"from" : "",
"to" : "27836500923",
"body" : "Testing of API in FreeQ code",
"encoding" : "TEXT",
"protocolId" : 0,
"messageClass" : 0,
"submission" : {
"id" : "1-00000000001100359398",
"date" : "2020-10-31T23:04:08Z"
},
"status" : {
"id" : "ACCEPTED.null",
"type" : "ACCEPTED",
"subtype" : null
},
"relatedSentMessageId" : null,
"userSuppliedId" : "testing123",
"numberOfParts" : null,
"creditCost" : null
} ]
Класс объектов c # является
public class SMSResponseObject
{
[JsonPropertyName("SMSResponseBody")]
public List<SMSResponseBody> SMSResponseBodies { get; set; }
}
public class SMSResponseBody
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("from")]
public string From { get; set; }
[JsonPropertyName("to")]
public string To { get; set; }
[JsonPropertyName("body")]
public string Body { get; set; }
[JsonPropertyName("encoding")]
public string Encoding { get; set; }
[JsonPropertyName("protocolId")]
public int ProtocolId { get; set; }
[JsonPropertyName("messageClass")]
public int MessageClass { get; set; }
[JsonPropertyName("submission")]
public Submission Submission { get; set; }
[JsonPropertyName("status")]
public Status Status { get; set; }
[JsonPropertyName("relatedSentMessageId")]
public object RelatedSentMessageId { get; set; }
[JsonPropertyName("userSuppliedId")]
public object UserSuppliedId { get; set; }
[JsonPropertyName("numberOfParts")]
public object NumberOfParts { get; set; }
[JsonPropertyName("creditCost")]
public object CreditCost { get; set; }
}
public class Status
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("subtype")]
public object Subtype { get; set; }
}
Я получаю ответ об ошибке
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'SMSResponseObject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
У меня такое чувство, что я упускаю здесь что-то важное, я был бы признателен за помощь, поскольку я не эксперт в объектно-ориентированном программировании на c #.
Комментарии:
1. где ваш класс отправки? и так далее? у вас есть все? Есть веб-сайты, где вы можете ввести свой json и получить класс C #, например: json2csharp.com
2. Чтобы сгенерировать классы C # из JSON, вы также можете использовать пункт меню «Правка> Вставить специальный> Вставить JSON как классы» в Visual Studio
Ответ №1:
Ошибка довольно очевидна в том, в чем проблема:
Невозможно десериализовать текущий массив JSON (например, [1,2,3]) в тип ‘SMSResponseObject’, поскольку для правильного десериализации типа требуется объект JSON (например, {«name»:»value»})
JSON представляет собой коллекцию (т. Е. Окружен [
и ]
). И вы пытаетесь выполнить десериализацию в один объект (например SMSResponseObject
), что вызывает ошибку.
Вместо этого вы должны десериализовать непосредственно в List<SMSResponseBody>
:
return DeserializeJsonFromStream<List<SMSResponseBody>>(stream)
Или, в качестве альтернативы, отправителю потребуется обернуть массив JSON в корневое свойство, соответствующее вашему SMSResponseObject
классу:
{
"SMSResponseBody": [ {
"id" : "904506056107888640",
"type" : "SENT",
"from" : "",
"to" : "27836500923",
"body" : "Testing of API in FreeQ code",
"encoding" : "TEXT",
"protocolId" : 0,
"messageClass" : 0,
"submission" : {
"id" : "1-00000000001100359398",
"date" : "2020-10-31T23:04:08Z"
},
"status" : {
"id" : "ACCEPTED.null",
"type" : "ACCEPTED",
"subtype" : null
},
"relatedSentMessageId" : null,
"userSuppliedId" : "testing123",
"numberOfParts" : null,
"creditCost" : null
} ]
}
Комментарии:
1. Спасибо, это сработало отлично! Первая часть, чтобы вернуть его в список вместо объекта. Как ни странно, это то, что у меня было в первую очередь, и это выдавало ошибки компилятора. Возможно, какая-то опечатка и недостаток веры.
Ответ №2:
Вам необходимо выполнить десериализацию в объект, который реализует ICollection или IList, как указано в сообщении об ошибке.
Вот рабочий пример с использованием того же кода, который вы предоставили.
Десериализатор (консольное приложение)
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace json_to_obj
{
class Program
{
static void Main(string[] args)
{
var serializer = Newtonsoft.Json.JsonSerializer.CreateDefault();
var data = GetRawData();
data.Position = 0;
var obj = serializer.Deserialize<List<SMSResponseBody>>(new JsonTextReader(new StreamReader(data)));
}
static Stream GetRawData() {
var data = new MemoryStream();
using(var stream = File.OpenRead("data.txt")) {
stream.CopyTo(data);
}
return data;
}
}
}
Model (POCOs)
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace json_to_obj
{
public class SMSResponseObject
{
[JsonPropertyName("SMSResponseBody")]
public List<SMSResponseBody> SMSResponseBodies { get; set; }
}
public class SMSResponseBody
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("from")]
public string From { get; set; }
[JsonPropertyName("to")]
public string To { get; set; }
[JsonPropertyName("body")]
public string Body { get; set; }
[JsonPropertyName("encoding")]
public string Encoding { get; set; }
[JsonPropertyName("protocolId")]
public int ProtocolId { get; set; }
[JsonPropertyName("messageClass")]
public int MessageClass { get; set; }
[JsonPropertyName("submission")]
public Submission Submission { get; set; }
[JsonPropertyName("status")]
public Status Status { get; set; }
[JsonPropertyName("relatedSentMessageId")]
public object RelatedSentMessageId { get; set; }
[JsonPropertyName("userSuppliedId")]
public object UserSuppliedId { get; set; }
[JsonPropertyName("numberOfParts")]
public object NumberOfParts { get; set; }
[JsonPropertyName("creditCost")]
public object CreditCost { get; set; }
}
public class Status
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("subtype")]
public object Subtype { get; set; }
}
public class Submission
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("date")]
public DateTime Date { get; set; }
}
}
Данные (необработанный текст JSON в файле «data.txt «)
[ {
"id" : "904506056107888640",
"type" : "SENT",
"from" : "",
"to" : "27836500923",
"body" : "Testing of API in FreeQ code",
"encoding" : "TEXT",
"protocolId" : 0,
"messageClass" : 0,
"submission" : {
"id" : "1-00000000001100359398",
"date" : "2020-10-31T23:04:08Z"
},
"status" : {
"id" : "ACCEPTED.null",
"type" : "ACCEPTED",
"subtype" : null
},
"relatedSentMessageId" : null,
"userSuppliedId" : "testing123",
"numberOfParts" : null,
"creditCost" : null
} ]
Десериализованный список
Комментарии:
1. Спасибо, что нашли время для revew и создания тестового примера. Я внедрил, как показано ниже.