我正在使用一个返回需要反序列化的json对象的API。我的问题是这些对象的一个成员有时是一个空数组(“[]”),有时是一个字典(“{”1“:{...},”2“:{...}}” )。我想将它反序列化为数组或字典,因为我不关心ID,我只想要所有对象的列表。这是我反序列化对象的方法:
var response = JsonConvert.DeserializeObject<Response>(json);
以下是Response类的定义:
public class Response
{
[JsonProperty(PropertyName = "variations")]
public Dictionary<int, Variation> Variations { get; set; }
}
当Response在其变体字段中包含字典时,它运行良好,但在包含空数组时失败。我从Newtonsoft得到一个错误,说数组无法反序列化为字典。如果我将Variations属性定义为数组,它适用于空数组,但是当它是字典时它会失败。我可以做什么来正确地反序列化两个可能的值,或者忽略空数组并将Variations设置为null,当它是一个数组而不是失败时。
感谢。
答案 0 :(得分:2)
这是卡尔的例子中的变化(对双关语而言)。我有类似的需求,但我没有返回字典,而是需要一个数组。我正在使用的API说它返回一个数组。但是,如果结果中只有一个项目,则将其作为对象返回!
public class VarationsContainer
{
[JsonIgnore]
public Varation[] Varations
{
get
{
return ParseObjectToArray<Variation>(VariationObject);
}
}
[JsonProperty(PropertyName = "varations")]
public object VarationsObject { get; set; }
protected T[] ParseObjectToArray<T>(object ambiguousObject)
{
var json = ambiguousObject.ToString();
if (String.IsNullOrWhiteSpace(json))
{
return new T[0]; // Could return null here instead.
}
else if (json.TrimStart().StartsWith("["))
{
return JsonConvert.DeserializeObject<T[]>(json);
}
else
{
return new T[1] { JsonConvert.DeserializeObject<T>(json) };
}
}
}
我希望这对其他一些悲伤的API消费者有用。
答案 1 :(得分:1)
以下是我使用的解决方案:
public Dictionary<int, Variation> Variations
{
get
{
var json = this.VariationsJson.ToString();
if (json.RemoveWhiteSpace() == EmptyJsonArray)
{
return new Dictionary<int, Variation>();
}
else
{
return JsonConvert.DeserializeObject<Dictionary<int, Variation>>(json);
}
}
}
[JsonProperty(PropertyName = "variations")]
public object VariationsJson { get; set; }
基本上,变体首先在基本对象中反序列化。当我想读取值时,我检查对象是否为空数组,如果是,我返回一个空字典。如果对象是一个好的字典,我将其反序列化并返回它。
答案 2 :(得分:1)
这是使用JsonConverter的替代解决方案
public class Response
{
[JsonProperty(PropertyName = "variations")]
[JsonConverter(typeof(EmptyArrayOrDictionaryConverter))]
public Dictionary<int, Variation> Variations { get; set; }
}
public class EmptyArrayOrDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(Dictionary<string, object>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return token.ToObject(objectType);
}
else if (token.Type == JTokenType.Array)
{
if (!token.HasValues)
{
// create empty dictionary
return Activator.CreateInstance(objectType);
}
}
throw new JsonSerializationException("Object or empty array expected");
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}