问题
I have an issue with the default serialization CamelCasing behavior of .Net Core and was hoping to see if someone else faced the same issue and what work around they used.
Property Names like FOO12 or FOO1 are incorrectly serialized to something like
foO12 or foO1
When infact they should probably be done as foo12 or foo1.
I have used a workaround of adding the following Attribute but was hoping somebody might have a better answer to this issue:
[JsonProperty(PropertyName = "foo12")]
回答1:
Json.NET's CamelCasePropertyNamesContractResolver
uses a CamelCaseNamingStrategy
to convert the property names to camelcase. Internally it uses StringUtils.ToCamelCase
which doesn't convert a character to lowercase in case it is followed by a number, see link.
CamelCaseNamingStrategy
public class CamelCaseNamingStrategy : NamingStrategy
{
// ...
protected override string ResolvePropertyName(string name)
{
return StringUtils.ToCamelCase(name);
}
}
StringUtils
Notice the 2nd if
statement, where there's no check for a number.
internal static class StringUtils
{
public static string ToCamelCase(string s)
{
if (!string.IsNullOrEmpty(s) && char.IsUpper(s[0]))
{
char[] array = s.ToCharArray();
for (int i = 0; i < array.Length && (i != 1 || char.IsUpper(array[i])); i++)
{
bool flag = i + 1 < array.Length;
if ((i > 0 & flag) && !char.IsUpper(array[i + 1])) // << Missing check for a number.
{
break;
}
char c = char.ToLower(array[i], CultureInfo.InvariantCulture);
array[i] = c;
}
return new string(array);
}
return s;
}
}
You can implement a custom NamingStrategy
to implement this missing check as shown below.
class CustomCamelCaseNamingStrategy : CamelCaseNamingStrategy
{
protected override String ResolvePropertyName(String propertyName)
{
return this.toCamelCase(propertyName);
}
private string toCamelCase(string s)
{
if (!string.IsNullOrEmpty(s) && char.IsUpper(s[0]))
{
char[] array = s.ToCharArray();
for (int i = 0; i < array.Length && (i != 1 || char.IsUpper(array[i])); i++)
{
bool flag = i + 1 < array.Length;
if ((i > 0 & flag) && !char.IsUpper(array[i + 1]) && !char.IsNumber(array[i + 1]))
{
break;
}
char c = char.ToLower(array[i], CultureInfo.InvariantCulture);
array[i] = c;
}
return new string(array);
}
return s;
}
}
In ConfigureServices
you assign this custom NamingStrategy
to the CamelCasePropertyNamesContractResolver
.
There's no need to implement a full custom ContractResolver
.
(When using the default CamelCaseNamingStrategy
, the CamelCasePropertyNamesContractResolver
sets the properties ProcessDictionaryKeys
and OverrideSpecifiedNames
to True
, so we keep this behaviour.)
services
.AddMvc()
.AddJsonOptions(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver() {
NamingStrategy = new CustomCamelCaseNamingStrategy() {
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
}});
来源:https://stackoverflow.com/questions/52374261/issue-with-default-camelcase-serialization-of-all-caps-property-names-to-json-in