Создание класса c # для приема массива JSON

#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 и создания тестового примера. Я внедрил, как показано ниже.