10

我正在使用 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 中,尝试颠倒顺序,以便基类属性排在第一位,但我还没有取得任何成功。我错过了一些微不足道的事情吗?

4

3 回答 3

3

我认为您不需要更改 JSON.Net 的代码即可。显然,您可以使用自定义合同解析器来做到这一点 - 通过从DefaultContractResolver继承- 如在json.net 论坛上遇到类似问题的人粘贴的这段代码所示。该海报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;
    }
}

另请参阅此项目以获取过滤要序列化的属性的类似代码。

于 2013-11-11T15:10:29.940 回答
2

只是为了补充,我提出了另一种与[JsonProperty(Order = -2)]此处使用的接受答案不同的方法:

在 JSON.NET 中序列化派生类时的字段顺序

于 2017-08-15T09:32:46.173 回答
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;
    }
}
于 2021-04-24T17:47:32.927 回答