Проблема с сериализацией CamelCase по умолчанию имен всех свойств Caps в JSON в ядре ASP.Net - PullRequest
0 голосов
/ 17 сентября 2018

У меня проблема со стандартным поведением CamelCasing для сериализации по умолчанию .Net Core, и я надеялся увидеть, сталкивался ли кто-то еще с той же проблемой и какой обходной путь он использовал.

Имена свойств, такие как FOO12 или FOO1, неверныСериализовано что-то вроде

foO12 или foO1

Когда на самом деле они должны быть выполнены как foo12 или foo1.

Я использовал обходной путь для добавления следующего атрибута, но надеялся, что кто-то может найти лучший ответ на этот вопрос:

[JsonProperty (PropertyName = "foo12")]

1 Ответ

0 голосов
/ 17 сентября 2018

Json.NET CamelCasePropertyNamesContractResolver использует CamelCaseNamingStrategy для преобразования имен свойств в camelcase. Внутренне он использует StringUtils.ToCamelCase, который не преобразует символ в нижний регистр, если за ним следует число, см. ссылка .

CamelCaseNamingStrategy

public class CamelCaseNamingStrategy : NamingStrategy
{
    // ...

    protected override string ResolvePropertyName(string name)
    {
        return StringUtils.ToCamelCase(name);
    }
}

StringUtils

Обратите внимание на 2-й оператор if, где нет проверки номера.

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;
    }
}

Вы можете реализовать custom NamingStrategy для реализации этой пропущенной проверки, как показано ниже.

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;
    }
}

В ConfigureServices этот пользовательский NamingStrategy назначается на CamelCasePropertyNamesContractResolver.
Нет необходимости реализовывать полный кастом ContractResolver.
(При использовании значения по умолчанию CamelCaseNamingStrategy CamelCasePropertyNamesContractResolver устанавливает свойства ProcessDictionaryKeys и OverrideSpecifiedNames на True, поэтому мы сохраняем это поведение.)

services
    .AddMvc()
    .AddJsonOptions(options => 
        options.SerializerSettings.ContractResolver = 
            new CamelCasePropertyNamesContractResolver() { 
                NamingStrategy = new CustomCamelCaseNamingStrategy() { 
                ProcessDictionaryKeys = true,
                OverrideSpecifiedNames = true 
        }});
...