Проблема с DeserializeObject Json String - PullRequest
0 голосов
/ 23 марта 2020

Я получаю следующий json формат строки из API:

{
   "Items":[
      {
         "Item":{
            "Codes":{},
            "Date":1523539700000,
            "Name":"Item1",
            "Price":"15"
         }
      },
      {
         "Item":{
            "Codes":{
               "productcode":"a",
               "departmentcode":"b",
               "storecode":"c"
            },
            "Date":1523537700000,
            "Name":"Item2",
            "Price":"20"
         }
      },
      {
         "Item":{
            "Codes":{
               "productcode":"a",
               "departmentcode":"b",
               "storecode":"c"
            },
            "date":1523539700000,
            "name":"Item3",
            "price":"30"
         }
      }
   ]
}

Я не заинтересован в элементе Codes, а затем создал следующий класс:

public class Item
    {
        [JsonConverter(typeof(ConvertItemDateTime))]
        [JsonProperty(PropertyName = "dateReceived")]
        public DateTime DateReceived { get; set; }
        [JsonProperty(PropertyName = "name")]
        public string Name{ get; set; }
        [JsonProperty(PropertyName = "price")]
        public double Price{ get; set; }
        public IList<Items> itemListResults { get; set; } //For view
        public int productid; // Added for view
    }

I затем попробуйте разобрать его ...

JObject jsondata = JObject.Parse(responseToString(response))
var values = json.GetValue("Items");

... который к этому моменту я вижу, что переменная 'values' по-прежнему содержит каждое значение (Date, Name, Price) внутри каждого элемента. Затем я пытаюсь десериализовать его ...

IList<Items> itemList = new List<Items>();
itemList = JsonConvert.DeserializeObject<IList<Items>>(values.ToString());

Когда я отлаживаю с этого момента, я вижу список с точным количеством ожидаемых предметов, но со всеми значениями (Дата, Имя, Цена) являются нулевыми Значение Date внутри json изменится (со стороны API). Иногда это будет длинный, а иногда строковый формат даты, содержащий «[GMT]».

Мой метод ConvertItemDateTime выглядит следующим образом:

public class ConvertItemDateTime : JsonConverter
    {
        private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        public override bool CanConvert(Type objectType)
        {
            Console.WriteLine(objectType);
            return true;
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Console.WriteLine(value.GetType());
            long ticks;
            if (value is DateTime)
            {
                var dateTime = (DateTime)value;
                ticks = (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalMilliseconds;
            }
            else if (value is DateTimeOffset)
            {
                var dateTimeOffset = (DateTimeOffset)value;
                ticks = (long)(dateTimeOffset.ToUniversalTime() - UnixEpoch).TotalMilliseconds;
            }
            else
            {
                throw new JsonSerializationException("Expected date object value.");
            }
            if (ticks < 0)
            {
                throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970.");
            }
            writer.WriteValue(ticks);
        }
        public override bool CanRead
        {
            get { return true; }
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            long ticks;
            if (reader.TokenType == JsonToken.Integer)
            {
                ticks = (long)reader.Value;
            }
            else if (reader.TokenType == JsonToken.String)
            {
                var stringValue = reader.Value.ToString();
                if (stringValue.Contains("[GMT]"))
                {
                    stringValue = stringValue.Substring(0, stringValue.Length - 6);
                    DateTime createdDate = DateTime.Parse(stringValue);
                    return createdDate;
                }

                if (!long.TryParse((string)reader.Value, out ticks))
                {
                    throw new JsonSerializationException("Cannot convert invalid value.");
                }
            }
            else
            {
                throw new JsonSerializationException("Unexpected token parsing date.");
            }
            if (ticks >= 0)
            {
                DateTime d = UnixEpoch.AddMilliseconds(ticks);
                Type t = objectType;
                if (t == typeof(DateTimeOffset))
                {
                    return new DateTimeOffset(d, TimeSpan.Zero);
                }
                return d;
            }
            else
            {
                throw new JsonSerializationException("Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970.");
            }
        }
    }
}

Пожалуйста, помогите мне заставить это работать.

Ответы [ 2 ]

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

Вот полный рабочий пример:

это моя модель:

  public class RootObject
  {
    public List<ItemContainer> Items { get; set; }
  }
  public class ItemContainer
  {
    public Item Item { get; set; }
  }
  public class Item
  {
    public Codes Codes { get; set; }
    public string Date { get; set; }
    public string Name { get; set; }
    public string Price { get; set; }
  }
  public class Codes
  {
    public string Productcode { get; set; }
    public string Departmentcode { get; set; }
    public string Storecode { get; set; }
  }

Вот как я ее десериализовал:

var result = JsonConvert.DeserializeObject<RootObject>(json);//json is a string that contains the json input.

Я заметил несколько проблемы с вашим примером:

  1. DataReceived - это свойство, которое не существует в модели json.
  2. Ваш Json несовместим. Имя, дата и цена также указаны в нижнем регистре: дата, имя и цена. Ваш json должен быть последовательным.
  3. Вы пытаетесь сделать слишком много в одном месте. Вы должны просто принять ввод даты в виде строки, а затем преобразовать ее в один или несколько полезных форматов или типов. Сохраняйте простоту десериализации / сериализации и избавьте себя от головной боли.
0 голосов
/ 23 марта 2020

Вы не можете просто десериализовать в IList, вам нужен объект, обладающий свойством Items. Например:

public class RootObject
{
    public IList<Item> Items { get; set; }
}

Другая проблема, которую я вижу, состоит в том, что JsonProperty для вашего свойства DateReceived должно совпадать с именем JSON, которое просто date.

...