10

json.net を使用して、テキスト エディターで編集できるようにしたいシリアル化されたオブジェクトを格納しています。オブジェクトの名前を含む基本クラスと、それを継承して他のプロパティを追加するクラスがあります。

問題は、派生クラスのプロパティが最初に書き込まれ、次に基本クラスのプロパティが書き込まれるようにプロパティが書き出されることです。したがって、次のようになります。

{
  "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 のコードを変更する必要はないと思います。どうやら、json.netフォーラムで同様の問題を抱えている人が貼り付けたこのコードに示されているように、DefaultContractResolverから継承することにより、カスタムコントラクトリゾルバーでそれを行うことができます。そのポスターは、定義する型がどれだけ深く継承されているかによってプロパティをオーバーライドし、並べ替えます。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 に答える
0

属性を使用する代わりにカスタムソートを使用する目的を無効にする種類のOrderプロパティを設定しない限り、プロパティが null を返すため、@sinelaw の回答は機能しません。[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 に答える