【问题标题】:Inheriting DefaultContractResolver and treating referenced entities differently继承 DefaultContractResolver 并以不同方式处理引用的实体
【发布时间】:2016-12-20 12:56:40
【问题描述】:

我只想序列化更改的属性。我设法为根类型执行此操作,但它包含对要序列化的其他对象的引用(甚至可能属于同一类型)。

这是我的界面和 ContractResolver:

public interface ISelectiveJsonSerialize
{
    IList<string> PropertiesToSerialize { get; }
}

public class JsonSelectiveSerializeContractResolver : DefaultContractResolver
{
    private readonly IList<string> _propertiesToSerialize;

    public JsonSelectiveSerializeContractResolver(IList<string> propertiesToSerialize)
    {
        _propertiesToSerialize = propertiesToSerialize;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return base.CreateProperties(type, memberSerialization).Where(p => _propertiesToSerialize.Contains(p.PropertyName)).ToList();
    }
}

属性 PropertiesToSerialize 将有一个接收值的属性名称列表。

这就是我序列化的方式:

        string result = "";
        if (val is ISelectiveJsonSerialize)
        {
            // Don't serialize all properties
            var resolver = new JsonSelectiveSerializeContractResolver(((ISelectiveJsonSerialize)val).PropertiesToSerialize);
            var settings = new JsonSerializerSettings { ContractResolver = resolver };
            result = JsonConvert.SerializeObject(val, Formatting.None, settings);
        }
        else
        {
            // Default serialization
            result = JsonConvert.SerializeObject(val);
        }

        return result;

这是我可以序列化的类型的示例:

public class Category : BaseType
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            PropertiesToSerialize.Add("Name");
        }
    }

    private Category _category;
    public Category Category
    {
        get { return _category; }
        set
        {
            _category = value;
            PropertiesToSerialize.Add("Category");
        }
    }
}

正如你所理解的,如果我只为我的根类型设置一个类别,它有一个名称,它不会序列化名称,因为根 PropertiesToSerialize 不包含“名称”,如果它会序列化根实体的空名称。

帮助?

【问题讨论】:

  • 我正在考虑 ContractResolver 和 JsonConverter 之间的某种组合,但不知道该怎么做。
  • 你有没有考虑过使用视图模型?
  • 视图模型有何不同?这些类不是实体,它们可以被视为视图模型,我可以对它们做任何我想做的事情,这就是为什么添加要序列化的更改属性列表的原因。那么视图模型如何帮助我呢?
  • 您展示的Category 类与我称之为视图模型的东西相去甚远。它派生自某些基本类型(在您的情况下为 BaseType),并且您的属性的 getter 包含一些 C# 代码(例如 PropertiesToSerialize.Add)。
  • 我没有说它是,我说它也可能是..但你仍然没有说为什么视图模型会有所不同?如何在不将属性添加到 PropertiesToSerialized 列表的情况下使用我在问题中介绍的逻辑?

标签: c# json json.net


【解决方案1】:

您可以挂钩到 Json.NET 的 conditional property serialization 功能,以添加测试以确定给定属性在序列化之前是否已被修改:

public class JsonSelectiveSerializeContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        var shouldSerialize = property.ShouldSerialize;
        var name = property.PropertyName;
        property.ShouldSerialize = (o) =>
        {
            var selectiveSerialize = o as ISelectiveJsonSerialize;
            if (selectiveSerialize != null)
            {
                if (!selectiveSerialize.PropertiesToSerialize.Contains(name))
                    return false;
            }
            return shouldSerialize == null || shouldSerialize(o);
        };

        return property;
    }
}

示例fiddle

【讨论】:

    猜你喜欢
    • 2019-04-06
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 2013-11-16
    • 2017-07-09
    • 2013-12-19
    • 1970-01-01
    相关资源
    最近更新 更多