【问题标题】:Json.NET - controlling class object-properties deserializationJson.NET - 控制类对象属性反序列化
【发布时间】:2014-12-14 03:34:23
【问题描述】:

我有一个模型类 Link,它使用 JSON.Net 反序列化。

public class Link
{
    [JsonConstructor]
    internal Link(int id)
    {
        Id = id;
    }

    public int Id { get; internal set; }

    [JsonProperty("title")]
    public string Title { get; internal set; }

    [JsonProperty("description")]
    public string Description { get; internal set; }

... and so on

    public Avatar AuthorAvatar { get; internal set; }
}

头像包含三个属性:DefaultImageUriSmallImageUriMediumImageUri。是否可以在 Link 对象反序列化上创建 Avatar 对象,该对象将使用:author_avatarauthor_avatar_smallauthor_avatar_medium json 字段?

【问题讨论】:

  • 恐怕我不明白你的问题......
  • @t3chb0t 我只想从三个“JsonProperty”创建 AuthorAvatar - author_avatar、author_avatar_small、author_avatar_medium,而不是在 Link 类中有三个 Uri 字段:Uri AuthorAvatarDefault、Uri AuthorAvatarSmall、Uri AuthorAvatarMedium(我想要将它们“打包”到另一个名为 Avatar 的类中)

标签: c# json.net


【解决方案1】:

我相信您可以通过编写自己的JsonConverter 来实现这一点,这是一个示例(我省略了序列化部分,但实现与反序列化非常相似):

示例:

class Program
{
    private static void Main(string[] args)
    {
        var json = @"{  
                        id:1,
                        title: 'link title',
                        description: 'link description',
                        author_avatar:'link',
                        author_avatar_small:'small link',
                        author_avatar_medium:'medium link',
                     }";

        var obj = JsonConvert.DeserializeObject<Link>(json);
    }
}

类定义:

[JsonConverter(typeof(LinkSerializer))]
public class Link
{
    [JsonConstructor]
    public Link(int id)
    {
        Id = id;
    }

    [JsonIgnore]
    public int Id { get; internal set; }

    [JsonProperty("title")]
    public string Title { get; internal set; }

    [JsonProperty("description")]
    public string Description { get; internal set; }


    public Avatar AuthorAvatar { get; internal set; }
}

public class Avatar
{
    [JsonProperty("author_avatar")]
    public string DefaultImageUri { get; internal set; }
    [JsonProperty("author_avatar_small")]
    public string SmallImageUri { get; internal set; }
    [JsonProperty("author_avatar_medium")]
    public string MediumImageUri { get; internal set; }
}

自定义链接序列化器:

public class LinkSerializer : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return typeof (Link) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);

        //NOTE:I changed .ctor to publec to simplify the process, we can also check for JsonConstructor attribute on constructors and the call appropriate one
        var value = existingValue ?? Activator.CreateInstance(objectType, jObject["id"].Value<int>());
        Populate(objectType, jObject, value);

        var avatar = Activator.CreateInstance<Avatar>(); //Fill avatar object
        Populate(avatar.GetType(),jObject,avatar);

        objectType.GetProperty("AuthorAvatar").SetValue(value,avatar); //set avatar object

        return value;
    }

    private static void Populate(Type objectType, JObject jObject, object value)
    {
        var properties =
            objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        foreach (var p in properties)
        {
            var ignore = p.GetCustomAttribute<JsonIgnoreAttribute>();
            if (ignore != null)
                continue;

            var custom = p.GetCustomAttribute<JsonPropertyAttribute>();
            var name = custom != null ? custom.PropertyName : p.Name;

            var token = jObject[name];
            var obj = token != null
                ? token.ToObject(p.PropertyType)
                : p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;

            p.SetValue(value, obj);
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        //we just want to deserialize the object so we don't need it here, but the implementation would be very similar to deserialization
    }

【讨论】:

    【解决方案2】:

    你的意思是这样的吗?

    class Program
    {
        static void Main(string[] args)
        {
    
            string json =
            @"{
                Id: 1,
                author_avatar: 'abc',
                author_avatar_small: 'small',
                author_avatar_medium: 'medium'
            }";
            var link = JsonConvert.DeserializeObject<Link>(json);
        }
    }
    
    public class Link
    {
        public Link(string author_avatar, string author_avatar_small, string author_avatar_medium)
        {
            AuthorAvatar = new Avatar(author_avatar, author_avatar_small, author_avatar_medium);
        }
        public int Id { get; set; }
        public Avatar AuthorAvatar { get; set; }
    }
    
    public class Avatar
    {
        public Avatar(string author_avatar, string author_avatar_small, string author_avatar_medium)
        {
            DefaultImageUri = author_avatar;
            SmallImageUri = author_avatar_small;
            MediumImageUri = author_avatar_medium;
        }
        public string DefaultImageUri { get; set; }
        public string SmallImageUri { get; set; }
        public string MediumImageUri { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-22
      • 1970-01-01
      • 2015-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      相关资源
      最近更新 更多