考虑这两个类:

public Class Base {
    public string Id {get; set;}
    public string Name {get; set;}
    public string LastName {get; set;}
}

以及派生类:

public Class Derived : Base {
    public string Address {get; set;}
    public DateTime DateOfBirth {get; set;}
}

When serializing the Derived class using Json.Net:

Derived record = new Derived record(); {// Initialize here...}
JsonConvert.SerializeObject(record);

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

{ 
  "address": "test", 
  "date_of_birth" : "10/10/10",
  "id" : 007,
  "name" : "test name",
  "last_name": "test last name"
 }

What I need:

{ 
  "id" : 007,
  "name" : "test name",
  "last_name": "test last name"
  "address": "test", 
  "date_of_birth" : "10/10/10",      
 }

Question

Is it possible to have the base class properties come first, when serializing the derived class (without using [JsonProperty(Order=)] for each property of both classes)?

推荐答案

根据JSON standard,JSON对象是unordered set of name/value pairs.所以我的建议是不要担心财产秩序.不过,您可以通过创建自己的ContractResolver来获得所需的顺序,该ContractResolver继承自标准contract resolvers之一,然后覆盖CreateProperties:

public class BaseFirstContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) =>
        base.CreateProperties(type, memberSerialization)
            ?.OrderBy(p => p.DeclaringType.BaseTypesAndSelf().Count()).ToList();
}

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

然后像这样使用它:

// Cache an instance of the resolver for performance
static IContractResolver baseFirstResolver = new BaseFirstContractResolver { /* Set any required properties here e.g.  NamingStrategy = new CamelCaseNamingStrategy() */ };

// And use the cached instance when serializing and deserializing
var settings = new JsonSerializerSettings 
{ 
    ContractResolver = baseFirstResolver, 
    // Add your other settings here.
    TypeNameHandling = TypeNameHandling.Objects 
};
var json = JsonConvert.SerializeObject(derived, typeof(Base), Formatting.Indented, settings);

注:

  • 这种方法尤其适用于多级类型层次 struct ,因为它可以自动对层次 struct 中所有级别的属性进行正确排序

  • Newtonsoft推荐caching instances of contract resolvers%的最佳性能

演示小提琴here.

Json相关问答推荐

使用Powershell脚本将配置信息块添加到json文件

SWIFT中的网络经理

条件性构建/修改嵌套对象数组

Powershell v7 文本背景突出显示

Golang 解组行为:字段过多?

jolt 通配符如何用于 RHS?

MarkLogic REST 资源 API - 仅使用一个 POST 请求修补多个文档

Kotlin Android Room 处理 Moshi TypeConverter 中的空对象列表

Rails 控制器无需编码即可渲染 json

如何将动态复杂 json 解析为dart 对象或模型

boost::json::value 的大括号初始化将其从对象转换为数组

如何配置spring mvc 3在json响应中不返回null对象?

UTF-8 字符编码之战 json_encode()

如何使用 Kotlin + Jackson 将 JSON 反序列化为 List

如何使用 LWP 发出 JSON POST 请求?

如何使用 Newtonsoft.Json 包在 C#(4.0) 中解析我的 json 字符串?

嵌套 JSON:如何向对象添加(推送)新项目?

运算符不存在:json = json

python追加到json对象中的数组

Jersey 2.0 相当于 POJOMappingFeature