反序列化Json数组和简单对象

时间:2015-06-05 22:59:49

标签: c# arrays json deserialization

我反序列化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.

2 个答案:

答案 0 :(得分:3)

你真的不能做我认为你问的事。在第一种情况下,你在回来的对象中有一个集合。

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; }
}

你可能能够为dynamic成员使用ValueAdd,但这会带来一大堆恼人的问题,因为你仍然需要弄清楚它是否是包含一个集合或单个实例。

实际上我发现你有两个选择:

选项#1:弄清楚你是否拥有集合或单个实例的版本并反序列化为适当的类型。

选项#2:您可以联系API的作者并让他们发回一致的JSON结构吗?如果它根据是否存在一个或多个ValueAdd对象来更改结构,那么这是一个糟糕的API。

答案 1 :(得分:2)

使用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; }
}