关闭某些 类 的驼峰 JSON 序列化

Turn off camelcase JSON serialization for certain classes

希望有人能帮我解决这个看似简单的问题。 简而言之,我想对所有 属性 名称使用驼峰式大小写,但 属性 是 DataTable 时除外。在那种情况下,我希望列名在序列化时保持不变。

我有一个相当深的对象结构,我使用 JSON.NET 序列化为 JSON。我希望 属性 名称是驼峰式的,我不想在每个 class 上都添加属性,所以我使用以下代码:

public static class JsonHelper
{
    private static DefaultContractResolver _contractResolver = new DefaultContractResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy()
    };

    public static string SerializeObjectToJson(object obj)
    {
        string json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
        {
            ContractResolver = _contractResolver
        });

        return json;
    }
}
...
string json = JsonHelper.SerializeObjectToJson(myDataDTO);

效果很好。但是,我也有 ADO.NET DataTable 属性,在这种情况下,我想保持列名的大小写不变。

此处为简化示例:

public class MySampleDTO
{
    public Object Data { get; init; }
    public int SomeInteger { get; init; }
}
...
// Get table with columns "Period", "Sales" and "Expenses"
DataTable myDataTable = ...
MySampleDTO dto = new MySampleDTO() {
   Data = myDataTable,
   SomeInteger = 3
}
string json = JsonHelper.SerializeObjectToJson(dto);

结果 JSON 变为:

{
  "data": [
    {
      "period": "2004",
      "sales": 400,
      "expenses": 700
    },
    {
      "period": "2005",
      "sales": 500,
      "expenses": 900
    },
    {
      "period": "2006",
      "sales": 720,
      "expenses": 420
    }
  ],
  "someInteger": 3
}

显然,数据的列名 table 被序列化为驼峰式,这不是我想要的(但我希望“SomeInteger”是驼峰式)

有什么办法可以解决这个问题吗?

Json.NET 使用 DataTableConverterDataTableJSON 相互转换。

这个与所有其他用于对象序列化(反)序列化的转换器共享同一个序列化器,在本例中是一个配置了驼峰命名策略的序列化器。

为了对 DataTable 应用不同的命名策略,您可以实施自定义 DataTableConverter,在其中将 serializer 配置为使用不同的 IContractResolver /DefaultContractResolver 在(反)序列化 DataTable.

时没有驼峰命名策略

或者,您可以设置一个完全不同的序列化程序,然后传递给 base.WriteJsonbase.ReadJson


public class CustomDataTableConverter : DataTableConverter
{
    private static readonly IContractResolver _contractResolver = new DefaultContractResolver();

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var contractResolver = serializer.ContractResolver;

        try
        {
            serializer.ContractResolver = _contractResolver;
            base.WriteJson(writer, value, serializer);
        }
        finally
        {
            serializer.ContractResolver = contractResolver;
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var contractResolver = serializer.ContractResolver;
        object value = null;

        try
        {
            serializer.ContractResolver = _contractResolver;
            value = base.ReadJson(reader, objectType, existingValue, serializer);
        }
        finally
        {
            serializer.ContractResolver = contractResolver;
        }

        return value;
    }
}

您将此 CustomDataTableConverter 添加到您 JsonSerializerSettings 的转换器中。

var settings = new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy()
    },
    Formatting = Newtonsoft.Json.Formatting.Indented        
};
settings.Converters.Add(new CustomDataTableConverter());

var datatable = new DataTable();
datatable.Columns.Add("Period", typeof(string));
datatable.Columns.Add("Sales", typeof(int));
datatable.Columns.Add("Expenses", typeof(int));
datatable.Rows.Add("2004",400, 700);
datatable.Rows.Add("2005", 500, 900);
datatable.Rows.Add("2006", 720, 420);

var dto = new MySampleDto
{
    Data = datatable,
    SomeInteger = 3
};

var json = JsonConvert.SerializeObject(dto, settings);

JSON 结果中 DataTable 的列现在将按预期为 PeriodSalesExpenses

{
  "data": [
    {
      "Period": "2004",
      "Sales": 400,
      "Expenses": 700
    },
    {
      "Period": "2005",
      "Sales": 500,
      "Expenses": 900
    },
    {
      "Period": "2006",
      "Sales": 720,
      "Expenses": 420
    }
  ],
  "someInteger": 3
}