我在将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());