我注意到当我序列化具有HTTP_VERB键的C#字典时,它变成JSON结构中的 httP_VERB 而不是hTTP_VERB或http_verb我预计驼峰案例会成功。
这是我用来重现问题的代码:
class Program {
static void Main(string[] args) {
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
var headers = new Dictionary<string, string>();
headers["SessionID"] = "123456";
headers["HTTP_VERB"] = "POST";
headers["HTTPVERSION"] = "1";
var data = new
{
headers = headers
};
string serializedEvent = JsonConvert.SerializeObject(data, settings);
if (serializedEvent.Contains("httP_VERB")) {
Console.WriteLine("Something is wrong with this camel case");
}
else {
Console.WriteLine("Sucess");
}
}
}
答案 0 :(得分:11)
没有办法让CamelCasePropertyNamesContractResolver
按照您想要的方式将字符串转换为驼峰,但您可以轻松编写自己的ContractResolver
。
我在CsCss项目中使用了PascalCase转换。经过一些调整后,结果如下:
public enum IdentifierCase
{
Camel,
Pascal,
}
public class CustomPropertyNamesContractResolver : DefaultContractResolver
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
public CustomPropertyNamesContractResolver (bool shareCache = false)
: base(shareCache)
{
Case = IdentifierCase.Camel;
PreserveUnderscores = true;
}
public IdentifierCase Case { get; set; }
public bool PreserveUnderscores { get; set; }
protected override string ResolvePropertyName (string propertyName)
{
return ChangeCase(propertyName);
}
private string ChangeCase (string s)
{
var sb = new StringBuilder(s.Length);
bool isNextUpper = Case == IdentifierCase.Pascal, isPrevLower = false;
foreach (var c in s) {
if (c == '_') {
if (PreserveUnderscores)
sb.Append(c);
isNextUpper = true;
}
else {
sb.Append(isNextUpper ? char.ToUpper(c, Culture) : isPrevLower ? c : char.ToLower(c, Culture));
isNextUpper = false;
isPrevLower = char.IsLower(c);
}
}
return sb.ToString();
}
// Json.NET implementation for reference
private static string ToCamelCase (string s)
{
if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0]))
return s;
var sb = new StringBuilder();
for (int i = 0; i < s.Length; ++i) {
if (i == 0 || i + 1 >= s.Length || char.IsUpper(s[i + 1]))
sb.Append(char.ToLower(s[i], Culture));
else {
sb.Append(s.Substring(i));
break;
}
}
return sb.ToString();
}
}
此转换器同时支持PascalCase
和camelCase
。它似乎以您期望的方式转换属性名称。
我从Json.NET中留下了oroginal ToCamelCase
函数作为参考。
示例程序:
internal class Program
{
private static void Main ()
{
var obj = new Dictionary<string, string> {
{ "SessionID", "123456" },
{ "HTTP_VERB", "POST" },
{ "HTTPVERSION", "1" },
};
var settings = new JsonSerializerSettings {
Formatting = Formatting.Indented,
ContractResolver = new CustomPropertyNamesContractResolver()
};
string strCamel = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine("camelCase: \n" + strCamel);
Console.WriteLine(strCamel.Contains("httP_VERB") ? "Something is wrong with this camel case" : "Success");
settings.ContractResolver = new CustomPropertyNamesContractResolver {
Case = IdentifierCase.Pascal,
PreserveUnderscores = false,
};
string strPascal = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine("PascalCase: \n" + strPascal);
Console.ReadKey();
}
}
输出:
camelCase:
{
"sessionId": "123456",
"http_Verb": "POST",
"httpversion": "1"
}
Success
PascalCase:
{
"SessionId": "123456",
"HttpVerb": "POST",
"Httpversion": "1"
}
答案 1 :(得分:1)
我需要以相反的顺序解决,即.NET中的JSON到Pascal-case非下划线属性中的小写下划线属性。 Discord的解决方案帮助我做到了这一点:
public class PascalCasePropertyNamesContractResolver : DefaultContractResolver
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
public PascalCasePropertyNamesContractResolver(bool shareCache = false)
: base(shareCache)
{
}
protected override string ResolvePropertyName(string s)
{
var sb = new StringBuilder(s.Length);
bool isNextUpper = false, isPrevLower = false;
for (var i = 0; i < s.Length; i++)
{
var c = s[i];
sb.Append(char.ToLower(c, Culture));
isNextUpper = i + 1 < s.Length && char.IsUpper(s[i + 1]);
if (isNextUpper && isPrevLower)
{
sb.Append("_");
}
isPrevLower = char.IsLower(c);
}
return sb.ToString();
}
}
答案 2 :(得分:1)
这对我有帮助。
var contractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
contractResolver.NamingStrategy = new Newtonsoft.Json.Serialization.SnakeCaseNamingStrategy();
settings.ContractResolver = contractResolver;
dynamic deserializedObject = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(requestResult.Content, settings);
您也可以尝试 CamelCaseNamingStrategy()代替SnakeCaseNamingStrategy();