Deserializing polymorphic json classes without type information using json.net

后端 未结 5 1065
暖寄归人
暖寄归人 2020-11-21 06:10

This Imgur api call returns a list containing both Gallery Image and Gallery Album classes represented in JSON.

I can\'t see how to

5条回答
  •  逝去的感伤
    2020-11-21 06:41

    Following implementation should let you de-serialize without changing the way you have designed your classes and by using a field other than $type to decide what to de-serialize it into.

    public class GalleryImageConverter : JsonConverter
    {   
        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(GalleryImage) || objectType == typeof(GalleryAlbum));
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            try
            {
                if (!CanConvert(objectType))
                    throw new InvalidDataException("Invalid type of object");
                JObject jo = JObject.Load(reader);
                // following is to avoid use of magic strings
                var isAlbumPropertyName = ((MemberExpression)((Expression>)(s => s.is_album)).Body).Member.Name;
                JToken jt;
                if (!jo.TryGetValue(isAlbumPropertyName, StringComparison.InvariantCultureIgnoreCase, out jt))
                {
                    return jo.ToObject();
                }
                var propValue = jt.Value();
                if(propValue) {
                    resultType = typeof(GalleryAlbum);
                }
                else{
                    resultType = typeof(GalleryImage);
                }
                var resultObject = Convert.ChangeType(Activator.CreateInstance(resultType), resultType);
                var objectProperties=resultType.GetProperties();
                foreach (var objectProperty in objectProperties)
                {
                    var propType = objectProperty.PropertyType;
                    var propName = objectProperty.Name;
                    var token = jo.GetValue(propName, StringComparison.InvariantCultureIgnoreCase);
                    if (token != null)
                    {
                        objectProperty.SetValue(resultObject,token.ToObject(propType)?? objectProperty.GetValue(resultObject));
                    }
                }
                return resultObject;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    
        public override bool CanWrite
        {
            get { return false; }
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

提交回复
热议问题