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