json.net:首先是序列化基类成员

时间:2013-11-11 14:50:30

标签: c# json json.net

我正在使用json.net来存储我希望人们能够在文本编辑器中编辑的序列化对象。我有一个基类,它包含对象的名称,然后是一个继承自该对象的类,并添加了一些其他属性。

问题是写出的属性首先写入派生类属性,然后写入基类afetr,所以我得到:

{
  "MySpecialFiled": 4,
  "Name": "This Is My Object",
  "AnotherBaseField": 8,
}

而不是:

{
  "Name": "This Is My Object",
  "AnotherBaseField": 8,
  "MySpecialFiled": 4,
}

当您在派生类中拥有一堆字段并希望在文本编辑器中实际查看/编辑时,您可以看到这有多痛苦!

我特别想弄乱源代码:

public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)

public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
在ReflectionUtils.cs中

,尝试颠倒顺序,以便首先获得基类属性,但我还没有取得任何成功。我错过了一些微不足道的事情吗?

3 个答案:

答案 0 :(得分:3)

我认为您不需要更改JSON.Net的代码。显然,您可以使用自定义合约解析程序 - 通过继承DefaultContractResolver - 在json.net论坛上的 this code pasted by someone with a similar issue 中显示。该海报覆盖CreateProperties并根据定义类型的继承深度对属性进行排序。

以下代码基于该帖子的代码(在CodePlex上由LittleColin提供)。 编译但未经过测试

public class CustomPropertySortContractResolver : DefaultContractResolver
{
    private const int MaxPropertiesPerContract = 1000;

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var members = GetSerializableMembers(type);
        if (members == null)
        {
            throw new JsonSerializationException("Null collection of serializable members returned.");
        }

        return members.Select(member => CreateProperty(member, memberSerialization))
                      .Where(x => x != null)
                      .OrderBy(p => (p.Order
                                       + (MaxPropertiesPerContract * GetTypeDepth(p.DeclaringType))) 
                                    ?? -1)
                      .ToList();
    }

    private static int GetTypeDepth(Type type)
    {
        int depth = 0;
        while ((type = type.BaseType) != null)
        {
            depth++;
        }

        return depth;
    }
}

另请参阅this project,了解过滤要序列化的属性的类似代码。

答案 1 :(得分:1)

为了补充,我建议使用[JsonProperty(Order = -2)]这里的另一种方法与接受的答案不同:

Order of fields when serializing the derived class in JSON.NET

答案 2 :(得分:0)

@sinelaw 的答案不起作用,因为属性 Order 返回 null,除非您使用 [JsonProperty(Order = <someInteger>)] 设置属性,这违背了使用自定义排序而不是使用 JsonProperty 的目的属性。

我已修改其 CustomPropertySortContractResolver 以在未找到此订单时使用默认属性订单。

<块引用>
public class CustomPropertySortContractResolver : DefaultContractResolver
{
    private const int MaxPropertiesPerContract = 1000;

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var members = GetSerializableMembers(type);
        if (members == null)
        {
            throw new JsonSerializationException("Null collection of serializable members returned.");
        }

        var propList = members
            .Select(member => CreateProperty(member, memberSerialization))
            .Where(x => x != null);

        var ind = 0;
        var orderedPropList = propList
            .OrderBy(p => ((p.Order != null ? p.Order : ind++) + (MaxPropertiesPerContract * GetTypeDepth(p.DeclaringType)) ?? -1))
            .ToList();

        return orderedPropList;
    }

    private static int GetTypeDepth(Type type)
    {
        int depth = 0;
        while ((type = type.BaseType) != null)
        {
            depth++;
        }

        return depth;
    }
}