Переконайтеся, що клавіші json мають малі літери в .NET


103

Чи є простий спосіб за допомогою JSON у .NET переконатися, що ключі надсилаються як малі регістри?

На даний момент я використовую бібліотеку Json.NET Newtonsoft і просто користуюся

string loginRequest = JsonConvert.SerializeObject(auth);

У цьому випадку authє лише наступний об’єкт

public class Authority
{
    public string Username { get; set; }
    public string ApiToken { get; set; }
}

Це призводить до

{"Username":"Mark","ApiToken":"xyzABC1234"}

Чи є спосіб переконатися, що клавіші usernameта apitokenключі проходять через малі літери?

Я не хочу просто запускати це, String.ToLower()звичайно, тому що значення для usernameі apitokenє змішаним регістром.

Я усвідомлюю, що я можу це зробити систематично і створити рядок JSON вручну, але мені це потрібно приблизно 20 або близько рядків даних JSON, і я бачу, чи можу я заощадити час. Мені цікаво, чи є вже побудовані бібліотеки, які дозволяють застосувати малі регістри для створення ключів.


Можливо, lib серіалізація json пропонує якісь атрибути серіалізації, які ви могли використовувати для зміни назв серіалізованих json ваших властивостей?
— тдаммери

@tdammers, дякую, я намагаюся знайти щось, що це робить, але поки що не вдалося. Сподіваючись, що хтось тут міг би вказати мені на це.
— Марк

1
Це може бути корисно у випадку, якщо ваша власність складається з одного слова.
— Ліпотам

Ага. У мене є протилежна проблема ... також - смішно, що ви згадуєте "Ім'я користувача" - це змішаний випадок. Ви мали на увазі "UserName"?
— BrainSlugs83

Не просто те, що значення, необхідні для того, щоб залишатись змішаними регістровими ключами, були лише тими, що мені потрібно торкнутися. Цінність залиште в спокої.
— Марк

Відповіді:


176

Ви можете створити для цього спеціальний вирішальник контрактів. Наступний вирішальник контракту перетворить усі ключі в малі регістри:

public class LowercaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        return propertyName.ToLower();
    }
}

Використання:

var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.SerializeObject(authority, Formatting.Indented, settings);

Вил в результаті:

{"username":"Mark","apitoken":"xyzABC1234"}

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

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static string SerializeObject(object o)
    {
        return JsonConvert.SerializeObject(o, Formatting.Indented, Settings);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return propertyName.ToLower();
        }
    }
}

Які можна використовувати так:

var json = LowercaseJsonSerializer.SerializeObject(new { Foo = "bar" });
// { "foo": "bar" }

ASP.NET MVC4 / WebAPI

Якщо ви використовуєте ASP.NET MVC4 / WebAPI, ви можете використовувати CamelCasePropertyNamesContractResolverбібліотеку Newtonsoft.Json, яка включена за замовчуванням.


будь-який розумний спосіб зробити це в зворотному порядку? Для десеріалізації?
— Shaun Rowan

1
@Anzeo Я не намагався це зробити сам, і жодної інформації про це не знайшов у документації. Рішенням було б перетворити JsonConvert.SerializeObject у свій власний клас. Дивіться моє оновлення.
— alexn

3
Здається, цей користувальницький вирішення контрактів не враховує атрибут JsonProperty, якщо ви хочете вказати винятки ... наприклад, [JsonProperty ("alternateName")] все ще стає нижчим регістром чи є інший спосіб зробити це?
— rekna

2
+1 для вказівки на CamelCasePropertyNamesContractResolver. Тепер я виявив, що System.Net.Http.Formatting.JsonContractResolverце за замовчуванням у WebAPI, і цей клас є внутрішнім. Я закінчую переписувати JsonContractResolverз верблюжої справи. Хтось повідомив, що це публічно aspnetwebstack.codeplex.com/workitem/228
— CallMeLaNN

10
CamelCasePropertyNamesContratResolverне перетворюйте властивості в малі регістри, лише перший знак.
— ToXinE

23
protected void Application_Start() {
    JsonConfig.Configure();   
}

public static class JsonConfig
{
    public static void Configure(){
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;

        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

10

У Json.NET 9.0.1 та пізніших версіях можна переконатися, що всі назви властивостей перетворюються у малі регістри за допомогою користувацького NamingStrategy. Цей клас витягує логіку алгоритмічного перекомпонування імен властивостей з вирішальника договору до окремого легкого об’єкта, на який можна встановити DefaultContractResolver.NamingStrategy. Це дозволяє уникнути необхідності створювати користувальницькийContractResolver і, таким чином, може бути простіше інтегруватися в рамки, які вже мають власні рішення для контрактів.

Визначте LowercaseNamingStrategyтак:

public class LowercaseNamingStrategy : NamingStrategy
{
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLowerInvariant();
    }
}

Потім серіалізуйте наступним чином:

var settings = new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver { NamingStrategy = new LowercaseNamingStrategy() },
};
string loginRequest = JsonConvert.SerializeObject(auth, settings);

Примітки -

  • Використання string.ToLowerInvariant()гарантує, що однаковий контракт формується у всіх регіонах.

  • Для того, щоб контролювати чи малі імена перевизначені власності, ключі словника і імена даних розширення, ви можете встановити NamingStrategy.OverrideSpecifiedNames, NamingStrategy.ProcessDictionaryKeysчи NamingStrategy.ProcessExtensionDataNames(Json.NET 10.0.1 і пізніше) до true.

  • Для кращого виконання можливостей ви захочете кешувати вирішувач контракту .

  • Якщо у вас немає доступу до налаштувань серіалізатора у ваших рамках, ви можете застосувати NamingStrategyбезпосередньо до свого об'єкта наступним чином:

    [JsonObject(NamingStrategyType = typeof(LowercaseNamingStrategy))]
    public class Authority
    {
        public string Username { get; set; }
        public string ApiToken { get; set; }
    }
  • Чи не модифікувати NamingStrategyв CamelCasePropertyNamesContractResolver. Цей укладач договору ділиться інформацією у всьому світі у всіх своїх випадках, і тому зміна будь-якого одного екземпляра може мати несподівані побічні ефекти.


8

ви можете використовувати "JsonProperty":

Використання:

public class Authority
{
    [JsonProperty("userName")] // or [JsonProperty("username")]
    public string Username { get; set; }
    [JsonProperty("apiToken")] // or [JsonProperty("apitoken")]
    public string ApiToken { get; set; }
}

var json  = JsonConvert.SerializeObject(authority);

0

Для мене я використав комбінацію деяких інших відповідей і закінчив це

        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });

був ближче до вирішення того, що я шукав, оскільки не шукав створити свою власну

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.