C# 在使用Netwonsoft库序列化JSON时,如何按字母顺序对属性排序?

C# 在使用Netwonsoft库序列化JSON时,如何按字母顺序对属性排序?,c#,.net,json,serialization,json.net,C#,.net,Json,Serialization,Json.net,使用Netwonsoft.JSON库序列化对象时,可以使用JsonPropertyAttributepropertyorder指定输出顺序。但是,我还希望在默认情况下按字母顺序对属性进行排序。您可以通过扩展Newtonsoft.Json.Serialization.DefaultContractResolver来创建自定义契约解析器。CreateProperties方法是负责属性顺序的方法,因此重写它并重新排序属性将以您想要的方式更改行为: public class OrderedContrac

使用Netwonsoft.JSON库序列化对象时,可以使用
JsonPropertyAttribute
property
order
指定输出顺序。但是,我还希望在默认情况下按字母顺序对属性进行排序。

您可以通过扩展
Newtonsoft.Json.Serialization.DefaultContractResolver
来创建自定义契约解析器。
CreateProperties
方法是负责属性顺序的方法,因此重写它并重新排序属性将以您想要的方式更改行为:

public class OrderedContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
    protected override System.Collections.Generic.IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(System.Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
    {
        var @base = base.CreateProperties(type, memberSerialization);
        var ordered = @base
            .OrderBy(p => p.Order ?? int.MaxValue)
            .ThenBy(p => p.PropertyName)
            .ToList();
        return ordered;
    }
}
然后使用上述设置对象的实例序列化:

using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
{
    var serializer = Newtonsoft.Json.JsonSerializer.Create(jsonSerializerSettings);
    serializer.Serialize(writer, jsonObject);
}
其中,
sw
是一个简单的字符串编写器:

var sb = new System.Text.StringBuilder();
var sw = new System.IO.StringWriter(sb);

jsonObject
是您希望序列化的对象。

您可以定义自己的ContractResolver:

public class CustomContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return base.CreateProperties(type, memberSerialization).OrderBy(x=>x.PropertyName).ToList();
    }
}

实际上,您可以通过实现
IContractResolver
或重写DefaultContractResolver的
CreateProperties
方法来控制顺序

下面是我的
IContractResolver
的一个简单实现示例,它按字母顺序排列属性:

public static class JsonHelper
{
    public class OrderedContractResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
        {
            return base.CreateProperties(type, memberSerialization)
                .OrderBy(p => p.Order ?? int.MaxValue)  // Honour any explit ordering first
                .ThenBy(p => p.PropertyName)
                .ToList();
        }
    }

    public static string SerialiseAlphabeticaly(object obj)
    {
        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new OrderedContractResolver() });
    }
}
公共类OrderedContractResolver:DefaultContractResolver { 受保护的重写System.Collections.Generic.IList CreateProperties(System.Type类型,MemberSerialization MemberSerialization) { 返回base.CreateProperties(type,memberSerialization).OrderBy(p=>p.PropertyName).ToList(); } } 然后设置设置并序列化对象,
JSON
字段将按字母顺序排列:

var settings=new JsonSerializerSettings()
{
ContractResolver=new OrderedContractResolver()
};
var json=JsonConvert.SerializeObject(对象,格式化,缩进,设置);

首先,如果要对代码中的元素进行排序,请使用。我使用这个类,它将使用该属性顺序(如果存在),然后按字母顺序排序:

public static class JsonHelper
{
    public class OrderedContractResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
        {
            return base.CreateProperties(type, memberSerialization)
                .OrderBy(p => p.Order ?? int.MaxValue)  // Honour any explit ordering first
                .ThenBy(p => p.PropertyName)
                .ToList();
        }
    }

    public static string SerialiseAlphabeticaly(object obj)
    {
        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new OrderedContractResolver() });
    }
}

对我来说,依赖JSON属性排序听起来很可疑。这是干什么用的?谁将使用这个“有序”JSON?如果你想表示排序,我觉得键值对数组似乎是更好的选择。对JSON属性进行排序的需要只是为了方便人们区分来自不同组件的JSON文件与我还想添加的中央用户,今天我遇到一个API提供者要求我提供一个请求JSON字符串的MD5摘要,以便在其末尾与之进行比较。involatile字符串需要对JSON属性进行排序。否则消息摘要将不进行比较。他们不使用键值对,主要是因为JSON对象不是平面的——它有层。JSON是为了让人可读。所以想要订购它们并不可疑。此外,如果系统无法按要求订购,则可以更轻松地分析任何差异。谢谢。但是,这会覆盖通过JsonProperty属性指定的顺序。您可能应该使用
StringComparer.Ordinal
对属性进行排序,以避免区域性特定的排序。例如,
.OrderBy(p=>p.PropertyName,StringComparer.Ordinal)
。将块与StringBuilder/StringWriter一起使用与只调用JsonConvert.SerializeObject(jsonObject,jsonSerializerSettings)有什么区别?
public static class JsonHelper
{
    public class OrderedContractResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
        {
            return base.CreateProperties(type, memberSerialization)
                .OrderBy(p => p.Order ?? int.MaxValue)  // Honour any explit ordering first
                .ThenBy(p => p.PropertyName)
                .ToList();
        }
    }

    public static string SerialiseAlphabeticaly(object obj)
    {
        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new OrderedContractResolver() });
    }
}
string json = JsonHelper.SerialiseAlphabeticaly(myObject);