当第一个项是要跟随的项的计数时,如何反序列化对象数组

本文关键字:反序列化 数组 对象 第一个 跟随 | 更新日期: 2023-09-27 18:24:58

我在将json反序列化为c#-对象时遇到以下问题。

我有一个json字符串,类似这样:

string data = 
@"{
    'response':
        [
            3,
            {
                'id': 1, 
                'name': 'john'
            },
            {
                'id': 1, 
                'name': 'john'
            },
            {
                'id': 1, 
                'name': 'john'
            }
        ]
 }";

和用于反序列化的类:

class Response 
{
    [JsonProperty(PropertyName = "response")]
    Item[] Items {get; set; }
}
class Item
{
    [JsonProperty(PropertyName = "id")]
    public int Id{get; set; }

    [JsonProperty(PropertyName = "name")]
    public int Id{get; set; }
}

然后我尝试反序列化它:

 var res = JsonConvert.DeserializeObject<Response>(data);

反序列化返回异常,并显示以下消息:"将值3转换为类型'Item'时出错。路径'response[0]',第1行,位置19。"很明显,发生这种情况是因为数据字符串中的数组"response"包含描述响应长度的文字"3"。我想知道,我可以在不编写自定义反序列化逻辑的情况下,仅通过json.net进行正确的反序列化吗?或者我需要创建自定义反序列化逻辑吗?

当第一个项是要跟随的项的计数时,如何反序列化对象数组

首先,您的模型应该进行一点校正

public class Response
{
    [JsonProperty(PropertyName = "response")]
    Item[] Items { get; set; }
}
public class Item
{
    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }
}

如果从json中删除3,则此反序列化将正确工作

var result = JsonConvert.DeserializeObject<Response>(json);

如果它来自一个你无法控制的服务器,那么你可以编写一个自定义的转换器

public class CustomConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Item);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value is long)
        {
            reader.Read(); //Skip this 3
            serializer.Converters.Remove(this); //avoid infinite recursion
        }
        return serializer.Deserialize<Item>(reader);
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

并反序列化为

var result = JsonConvert.DeserializeObject<Response>(json, new CustomConverter());

您甚至可以使用Linq获取Items 的列表

var items = JObject.Parse(json)["response"]
                .Skip(1)
                .OfType<JObject>()
                .Select(j=>j.ToObject<Item>())
                .ToList();

另一种方法

   class Response
    {
    [JsonProperty(PropertyName = "response")]
    public dynamic Items { get; set; }
    }

    var des = JsonConvert.DeserializeObject<Response>(data);
    var result = (des.Items as IEnumerable<Newtonsoft.Json.Linq.JToken>)
              .Select(delegate(JToken j){
        if (j.Type == JTokenType.Integer)
            return j.Value<int>();
        return JsonConvert.DeserializeObject<object>(j.ToString());
    }).ToList();
    var one = JsonConvert.DeserializeObject<Item>(result[1].ToString());