Обеспечение того, чтобы ключи json были строчными в .NET

Есть ли простой способ использовать JSON в .NET, чтобы гарантировать, что ключи отправляются в нижнем регистре?

На данный момент я использую библиотеку newtonsoft Json.NET и просто использую

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, и я смотрю, смогу ли я сэкономить время. Мне интересно, есть ли какие-нибудь уже созданные библиотеки, которые позволяют применять строчные буквы для создания ключей.


person Mark    schedule 09.06.2011    source источник
comment
Может быть, библиотека сериализации json предлагает какие-то атрибуты сериализации, которые вы могли бы использовать для изменения сериализованных имен json ваших свойств?   -  person tdammers    schedule 09.06.2011
comment
@tdammers, спасибо, я пытаюсь найти что-то, что делает это, но пока безуспешно. Надеюсь, что кто-то здесь может указать мне на это.   -  person Mark    schedule 09.06.2011
comment
Это может быть полезно, если вы хотите состоит из одного слова.   -  person Lipotam    schedule 17.07.2012
comment
Хм. У меня противоположная проблема ... также - забавно, что вы упоминаете имя пользователя в смешанном регистре. Вы имели в виду UserName?   -  person BrainSlugs83    schedule 23.10.2015
comment
Нет, просто значения должны оставаться смешанными, если только клавиши были тем, к чему мне нужно было прикоснуться. Ценность оставьте в покое.   -  person Mark    schedule 24.10.2015


Ответы (4)


Для этого вы можете создать собственный преобразователь контрактов. Следующий преобразователь контрактов преобразует все ключи в нижний регистр:

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, которая включена по умолчанию.

person alexn    schedule 09.06.2011
comment
какой-нибудь разумный способ сделать это наоборот? Для десериализации? - person Shaun Rowan; 04.03.2012
comment
Есть ли способ установить эти настройки по умолчанию? - person thomaux; 19.06.2012
comment
@Anzeo Я не пробовал делать это сам и не нашел информации об этом в документации. Решением было бы обернуть JsonConvert.SerializeObject в ваш собственный класс. Смотрите мое обновление. - person alexn; 21.06.2012
comment
Похоже, этот настраиваемый резольвер контрактов не принимает во внимание атрибут JsonProperty, если вы хотите указать исключения ... например. [JsonProperty (alternateName)] по-прежнему отображается в нижнем регистре или есть другой способ сделать это? - person rekna; 29.09.2012
comment
+1 за указание на CamelCasePropertyNamesContractResolver. Теперь я обнаружил, что System.Net.Http.Formatting.JsonContractResolver является значением по умолчанию в WebAPI, и этот класс является внутренним. В итоге я переписываю JsonContractResolver с верблюжьим футляром. Кто-то сообщил, что это общедоступный aspnetwebstack.codeplex.com/workitem/228 - person CallMeLaNN; 19.05.2013
comment
CamelCasePropertyNamesContratResolver не преобразовывать свойства в нижний регистр, только первый символ. - person ToXinE; 18.09.2015
comment
Хорошее решение! Есть идеи, хочу ли я реализовать это только для ОДНОГО действия WebAPI? Спасибо - person Aleksander Bethke; 22.08.2016
comment
Как верблюжий футляр только первый уровень свойств ?? - person Vlado Pandžić; 03.11.2017

В Json.NET 9.0.1 и более поздних версий возможно убедитесь, что все имена свойств преобразованы в нижний регистр с помощью настраиваемого NamingStrategy. Этот класс извлекает логику для алгоритмического переназначения имен свойств из преобразователя контрактов в отдельный легкий объект, который может быть установлен на _ 2_. Это избавляет от необходимости создавать пользовательский 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 или _ 10_ (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. Этот преобразователь контрактов разделяет информацию о типах глобально во всех своих экземплярах, поэтому изменение любого одного экземпляра может иметь неожиданные побочные эффекты.

person dbc    schedule 15.12.2017

вы можете использовать "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);
person Jorgelig    schedule 24.11.2017

Для меня я использовал комбинацию некоторых других ответов и в итоге получил это

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

был ближе к решению того, что я искал, поскольку я не стремился создавать свой собственный

person workabyte    schedule 11.02.2020