Json.NET 利用ContractResolver解决命名不一致问题

时间:2024-01-08 16:48:56

今天在遇到这么个问题,项目上有一部分功能需要访问web api, 这个api请求和相应的数据格式都是使用JSON,JSON中的field命名方式是以下划线分割的,比如"project_name", "account_id"等等。但是在C#中命名方式一般都为Camel-Case,这样如果使用Json.NET的默认设置序列化和反序列化对象的话就造成属性名不一致的情况。

这时,我们就可以通过Json.NET中的ContractResolver来实现实现属性的映射,比如将ProjectName映射为project_name:

public class UnderlineSplitContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return CamelCaseToUnderlineSplit(propertyName);
} private string CamelCaseToUnderlineSplit(string name)
{
StringBuilder builder = new StringBuilder();
for (int i = ; i < name.Length; i++)
{
var ch = name[i];
if (char.IsUpper(ch) && i > )
{
var prev = name[i - ];
if (prev != '_')
{
if (char.IsUpper(prev))
{
if (i < name.Length - )
{
var next = name[i + ];
if (char.IsLower(next))
{
builder.Append('_');
}
}
}
else
{
builder.Append('_');
}
}
} builder.Append(char.ToLower(ch));
} return builder.ToString();
}
}

代码中我继承了Json.NET中的DefaultContractResolver类,并且重写了ResolvePropertyName方法,在方法内部将以Camel-Case方式命名的属性名转换为以下划线分割的方式。

接着,使用UnderlineSplitContractResolver替代默认的DefaultContractRelover就可以达到想要的效果:

var settings = new JsonSerializerSettings
{
ContractResolver = new UnderlineSplitContractResolver()
}; var project = new Project(){ ProjectName = "test" };
var json = JsonConvert.SerializeObject(project, settings);
Console.WriteLine(json); //{ “project_name”: "test" } project = JsonConvert.DeserializeObject<Project>(json, settings);
Console.WriteLine(project.ProjectName); //test

通过无论是序列化还是反序列化都达到了效果,即:ProjectName -> project_name 和 project_name -> ProjectName