0

我从 API 获得以下 json 字符串格式:

{
   "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
    }

然后我尝试解析它...

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

...此时我可以看到变量“值”仍然包含每个项目内的每个值(日期、名称、价格)。然后我尝试反序列化它......

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

当我从这一点开始调试时,我可以看到一个列表,其中包含我期望的确切数量的项目,但所有值(日期、名称、价格)都是空的。json 中的 Date 值将发生变化(从 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.");
            }
        }
    }
}

请帮助我完成这项工作。

4

2 回答 2

0

您不能简单地反序列化为IList,您需要一个具有Items属性的对象。例如:

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

我可以看到的另一个问题是JsonPropertyfor your DateReceivedproperty 需要匹配 JSON 名称,即date.

于 2020-03-22T21:44:21.903 回答
0

这是一个完整的工作示例:

这是我的模型:

  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. 你试图在一个地方做太多事情。您应该只将日期的输入作为字符串,然后将其转换为一种或多种有用的格式或类型。保持你的反序列化/序列化简单,省去你的麻烦。
于 2020-03-22T22:03:03.390 回答