今天在遇到這麼個問題,項目上有一部分功能需要通路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 = 0; i < name.Length; i++)
{
var ch = name[i];
if (char.IsUpper(ch) && i > 0)
{
var prev = name[i - 1];
if (prev != '_')
{
if (char.IsUpper(prev))
{
if (i < name.Length - 1)
{
var next = name[i + 1];
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