Issue with Default camelCase serialization of All Caps property names to JSON in ASP.Net core

点点圈 提交于 2019-12-08 01:42:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!