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

A-S*_*ani 20 c# serialization json json.net

考虑这两个类:

public Class Base {
    public string Id {get; set;}
    public string Name {get; set;}
    public string LastName {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

派生类:

public Class Derived : Base {
    public string Address {get; set;}
    public DateTime DateOfBirth {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

使用Json.Net序列化Derived类:

Derived record = new Derived record(); {// Initialize here...}
JsonConvert.SerializeObject(record);
Run Code Online (Sandbox Code Playgroud)

默认情况下,Derived类的属性首先出现:

{ 
  "address": "test", 
  "date_of_birth" : "10/10/10",
  "id" : 007,
  "name" : "test name",
  "last_name": "test last name"
 }
Run Code Online (Sandbox Code Playgroud)

我需要的:

{ 
  "id" : 007,
  "name" : "test name",
  "last_name": "test last name"
  "address": "test", 
  "date_of_birth" : "10/10/10",      
 }
Run Code Online (Sandbox Code Playgroud)

在序列化派生类时(不使用两个类的每个属性),是否可以首先使用基类属性?[JsonProperty(Order=)]

Mos*_*taf 26

作为补充,另一种不同于接受答案的方法是使用[JsonProperty(Order = -2)]; 您可以修改基类,如下所示:

public class Base
{
    [JsonProperty(Order = -2)]
    public string Id { get; set; }

    [JsonProperty(Order = -2)]
    public string Name { get; set; }

    [JsonProperty(Order = -2)]
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

将顺序设置为-2的原因是没有显式顺序的任何属性默认为-1.因此,您必须为所有子属性提供一个订单,或者只是将基类的属性设置为-2.

  • 我认为 `[JsonProperty(Order = int.MinValue)]` 是不言自明的(-2 似乎是任意值) (3认同)
  • 你说得对。正如我所提到的,对于那些可能仅通过标题发现这个问题的人来说,这只是一个补充答案,标题更为笼统。因此这两种方法都可以在一个地方找到。 (2认同)

dbc*_*dbc 18

根据JSON标准,JSON对象是一组无序的名称/值对.所以我的建议是不要担心房产秩序.不过,您可以通过创建自己ContractResolver继承的标准合约解析器来获取所需的订单,然后覆盖CreateProperties:

public class BaseFirstContractResolver : DefaultContractResolver
{
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
    static BaseFirstContractResolver instance;

    static BaseFirstContractResolver() { instance = new BaseFirstContractResolver(); }

    public static BaseFirstContractResolver Instance { get { return instance; } }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        if (properties != null)
            return properties.OrderBy(p => p.DeclaringType.BaseTypesAndSelf().Count()).ToList();
        return properties;
    }
}

public static class TypeExtensions
{
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它像:

        var settings = new JsonSerializerSettings { ContractResolver = BaseFirstContractResolver.Instance };
        var json = JsonConvert.SerializeObject(derived, Formatting.Indented, settings);
Run Code Online (Sandbox Code Playgroud)