【问题标题】:Serialize member as Object or List<Object>将成员序列化为 Object 或 List<Object>
【发布时间】:2014-01-25 02:43:09
【问题描述】:

这有点类似于JSON.net - field is either string or List

假设我有以下 POCO 类,需要将 json 字符串反序列化为该类型。

public class Movie 
{
    [JsonProperty("title")]
    public List<string> Title { get; set; }

    [JsonProperty("images")]
    public List<Image> Images { get; set; }

    [JsonProperty("actors")]
    public List<Actor> Actors { get; set; }

    [JsonProperty("directors")]
    public List<Director> Directors { get; set; }    
}

假设需要反序列化的json字符串如下

{
    "title": "Movie title",
    "images": [ 
                {"url" : "http://www.url.com/img_3.jpg"},
                {"url" : "http://www.url.com/img_4.jpg"}
              ],
    "actors": [ 
                {"name" : "Steven Berkoff"},
                {"name" : "Nikolaj Coster-Waldau"},
                {"name" : "Julie Cox"}
              ],
    "directors": { "name" : "Simon Aeby" }
},
{  
    "title": "Movie title",
    "images": {"url" : "http://www.url.com/img_3.jpg"},                  
    "actors": {"name" : "Julie Cox"},                 
    "directors": { "name" : "Simon Aeby" }
}

这里的问题甚至认为 POCO 需要一个导演、演员和图像的列表,json 每种类型只有一种。尝试反序列化时会出错。

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    为那些可以识别列表中是否有一个或多个项目并将其应用于您的属性的列表创建一个转换器:

    public class SingleOrEnumerableJsonConverter<TEnumerable> : JsonConverter
            where TEnumerable : IEnumerable
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(TEnumerable).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var obj = serializer.Deserialize<JToken>(reader);
            return ConvertObject(obj) ?? GetDefaultValue();
        }
    
        private object GetDefaultValue()
        {
            return Activator.CreateInstance<TEnumerable>();
        }
    
        private object ConvertObject(JToken obj)
        {
            try
            {
                return obj.ToObject<TEnumerable>();
            }
            catch (JsonSerializationException)
            {
                // try as an array of object
                return new JArray { obj }.ToObject<TEnumerable>();
            }
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            object serializableValue = GetSerializableValue((TEnumerable)value, serializer);
            serializer.Serialize(writer, serializableValue);
        }
    
        private object GetSerializableValue(TEnumerable items, JsonSerializer serializer)
        {
            var arr = new JArray(items.Cast<object>()
                .Select(item => JToken.FromObject(item, serializer))
            );
            return arr.Count > 1 ? arr : arr.SingleOrDefault();
        }
    }
    
    public class Movie 
    {
        [JsonProperty("title")]
        [JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<string>>))]
        public List<string> Title { get; set; }
    
        [JsonProperty("images")]
        [JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Image>>))]
        public List<Image> Images { get; set; }
    
        [JsonProperty("actors")]
        [JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Actor>>))]
        public List<Actor> Actors { get; set; }
    
        [JsonProperty("directors")]
        [JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Director>>))]
        public List<Director> Directors { get; set; }    
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-14
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 2012-08-11
      • 2022-01-15
      • 2013-09-23
      • 1970-01-01
      相关资源
      最近更新 更多