反序列化 Json 个数组和简单对象
Deserialize Json arrays and simple object
我正在反序列化一个 JSON 响应,并且有一个对象可以是数组或简单对象,例如:
{
"ValueAdds":{
"@size":3,
"ValueAdd":[
{
"description":"desc 1"
},
{
"description":"desc 1"
}
]
}
}
另一种情况:
{
"ValueAdds": {
"@size": "1",
"ValueAdd": {
"description": "Internet inalámbrico gratuito"
}
}
}
实体:
public ValueAddsWrap
{
public ValueAddBase ValueAdds { set; get; }
}
public class ValueAddBase
{
public ValueAdd[] ValueAdd { set; get; }
}
public class ValueAdd
{
public string description { set; get; }
}
当我收到一个简单的对象时出现异常。我如何设计实体以反序列化一个数组和一个简单的对象?
我正在使用 Newtonsoft:
T resp_object = JsonConvert.DeserializeObject<T>(json);
例外情况:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'rce.bookings.business.expedia.Responses.ValueAdd[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
你真的做不到我认为你在问的事情。在第一种情况下,您在返回的对象中有一个集合。
public class ValueAdd
{
public string description { get; set; }
}
public class ValueAdds
{
public int size { get; set; }
public List<ValueAdd> ValueAdd { get; set; }
}
public class RootObject
{
public ValueAdds ValueAdds { get; set; }
}
在第二种情况下,您有一个对象的单个实例。
public class ValueAdd
{
public string description { get; set; }
}
public class ValueAdds
{
public string size { get; set; }
public ValueAdd ValueAdd { get; set; }
}
public class RootObject
{
public ValueAdds ValueAdds { get; set; }
}
您可以为 ValueAdd
成员使用 dynamic
,但这会带来一大堆烦人的问题,因为您仍然需要弄清楚它是否包含一个集合或单个实例。
实际上我看到你有两个选择:
选项 #1:弄清楚您是否拥有带有集合或单个实例的版本,然后反序列化为适当的类型。
选项 #2:您能否联系 API 的作者并让他们发回一致的 JSON 结构?如果它根据是否存在一个或多个 ValueAdd 对象来更改结构,那就太糟糕了 API。
使用 JsonConverter:
public class ValueAddsConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var valueAdds = new ValueAdds();
var jo = (JObject)JObject.Load(reader)["ValueAdds"];
valueAdds.Size = Int32.Parse((string)jo["@size"]);
if (valueAdds.Size > 1)
{
valueAdds.ValueAdd = jo["ValueAdd"].Children().Select(x => x.ToObject<ValueAdd>());
}
else
{
valueAdds.ValueAdd = new List<ValueAdd>{jo["ValueAdd"].ToObject<ValueAdd>()};
}
return valueAdds;
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof (ValueAdds));
}
}
public class ValueAdd
{
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
}
[JsonConverter(typeof (ValueAddsConverter))]
public class ValueAdds
{
public int Size { get; set; }
public IEnumerable<ValueAdd> ValueAdd { get; set; }
}
我正在反序列化一个 JSON 响应,并且有一个对象可以是数组或简单对象,例如:
{
"ValueAdds":{
"@size":3,
"ValueAdd":[
{
"description":"desc 1"
},
{
"description":"desc 1"
}
]
}
}
另一种情况:
{
"ValueAdds": {
"@size": "1",
"ValueAdd": {
"description": "Internet inalámbrico gratuito"
}
}
}
实体:
public ValueAddsWrap
{
public ValueAddBase ValueAdds { set; get; }
}
public class ValueAddBase
{
public ValueAdd[] ValueAdd { set; get; }
}
public class ValueAdd
{
public string description { set; get; }
}
当我收到一个简单的对象时出现异常。我如何设计实体以反序列化一个数组和一个简单的对象?
我正在使用 Newtonsoft:
T resp_object = JsonConvert.DeserializeObject<T>(json);
例外情况:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'rce.bookings.business.expedia.Responses.ValueAdd[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
你真的做不到我认为你在问的事情。在第一种情况下,您在返回的对象中有一个集合。
public class ValueAdd
{
public string description { get; set; }
}
public class ValueAdds
{
public int size { get; set; }
public List<ValueAdd> ValueAdd { get; set; }
}
public class RootObject
{
public ValueAdds ValueAdds { get; set; }
}
在第二种情况下,您有一个对象的单个实例。
public class ValueAdd
{
public string description { get; set; }
}
public class ValueAdds
{
public string size { get; set; }
public ValueAdd ValueAdd { get; set; }
}
public class RootObject
{
public ValueAdds ValueAdds { get; set; }
}
您可以为 ValueAdd
成员使用 dynamic
,但这会带来一大堆烦人的问题,因为您仍然需要弄清楚它是否包含一个集合或单个实例。
实际上我看到你有两个选择:
选项 #1:弄清楚您是否拥有带有集合或单个实例的版本,然后反序列化为适当的类型。
选项 #2:您能否联系 API 的作者并让他们发回一致的 JSON 结构?如果它根据是否存在一个或多个 ValueAdd 对象来更改结构,那就太糟糕了 API。
使用 JsonConverter:
public class ValueAddsConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var valueAdds = new ValueAdds();
var jo = (JObject)JObject.Load(reader)["ValueAdds"];
valueAdds.Size = Int32.Parse((string)jo["@size"]);
if (valueAdds.Size > 1)
{
valueAdds.ValueAdd = jo["ValueAdd"].Children().Select(x => x.ToObject<ValueAdd>());
}
else
{
valueAdds.ValueAdd = new List<ValueAdd>{jo["ValueAdd"].ToObject<ValueAdd>()};
}
return valueAdds;
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof (ValueAdds));
}
}
public class ValueAdd
{
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
}
[JsonConverter(typeof (ValueAddsConverter))]
public class ValueAdds
{
public int Size { get; set; }
public IEnumerable<ValueAdd> ValueAdd { get; set; }
}