Хранить корпус при сериализации словарей

У меня есть проект Web Api, который настраивается следующим образом:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

Тем не менее, я хочу, чтобы shell словарных ключей оставалась неизменной. есть ли какой-либо атрибут в Newtonsoft.Json Я могу использовать class для обозначения того, что я хочу, чтобы shell оставалась неизменной во время сериализации?

 public class SomeViewModel { public Dictionary Data { get; set; } } 

Для этого нет атрибута, но вы можете сделать это, настроив resolver.

Я вижу, что вы уже используете CamelCasePropertyNamesContractResolver . Если вы CreateDictionaryContract() новый class распознавателя и переопределите метод CreateDictionaryContract() , вы можете предоставить замену функции DictionaryKeyResolver , которая не изменяет имена ключей.

Вот код, который вам нужен:

 class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver { protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract contract = base.CreateDictionaryContract(objectType); contract.DictionaryKeyResolver = propertyName => propertyName; return contract; } } 

Демо-версия:

 class Program { static void Main(string[] args) { Foo foo = new Foo { AnIntegerProperty = 42, HTMLString = "", Dictionary = new Dictionary { { "WHIZbang", "1" }, { "FOO", "2" }, { "Bar", "3" }, } }; JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CamelCaseExceptDictionaryKeysResolver(), Formatting = Formatting.Indented }; string json = JsonConvert.SerializeObject(foo, settings); Console.WriteLine(json); } } class Foo { public int AnIntegerProperty { get; set; } public string HTMLString { get; set; } public Dictionary Dictionary { get; set; } } 

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

 { "anIntegerProperty": 42, "htmlString": "", "dictionary": { "WHIZbang": "1", "FOO": "2", "Bar": "3" } } 

Json.NET 9.0.1 представил NamingStrategy classов NamingStrategy для решения этой проблемы. Он извлекает логику алгоритмического переназначения имен свойств из распознавателя контрактов в отдельный, легкий class, который позволяет контролировать, будут ли переназначены ключи словаря , явно заданные имена свойств и имена данных расширений (в 10.0.1 ).

Используя DefaultContractResolver и установив NamingStrategy в экземпляр CamelCaseNamingStrategy вы можете сгенерировать JSON с именами свойств camel-cased и немодифицированными ключами словаря:

 var resolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = false, OverrideSpecifiedNames = true } }; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver; 

Заметки:

  • Текущая реализация CamelCasePropertyNamesContractResolver также указывает, что .Net-члены с явно указанными именами свойств (например, те, в которых установлено JsonPropertyAttribute.PropertyName ), должны иметь JsonPropertyAttribute.PropertyName имена:

     public CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; } 

    Вышеуказанный resolver сохраняет это поведение. Если вы этого не хотите, установите OverrideSpecifiedNames = false .

  • Json.NET имеет несколько встроенных страtagsй именования, включая:

    1. CamelCaseNamingStrategy . Страtagsя именования случаев верблюда, которая содержит логику переопределения имен, ранее встроенную в CamelCasePropertyNamesContractResolver .
    2. SnakeCaseNamingStrategy . Страtagsя именования змей .
    3. DefaultNamingStrategy . Страtagsя именования по умолчанию. Имена свойств и словарные ключи не изменяются.

    Или вы можете создать свой собственный, наследуя от абстрактного базового classа NamingStrategy .

  • Хотя также можно изменить NamingStrategy экземпляра CamelCasePropertyNamesContractResolver , поскольку последний делится информацией о контракте во всех экземплярах каждого типа , это может привести к неожиданным побочным эффектам, если ваше приложение пытается использовать несколько экземпляров CamelCasePropertyNamesContractResolver . Не существует такой проблемы с DefaultContractResolver , поэтому ее безопаснее использовать, когда требуется любая настройка логики корпуса.

Это очень хороший ответ. Но почему бы не просто переопределить ResolveDictionaryKey ?

 class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver { #region Overrides of DefaultContractResolver protected override string ResolveDictionaryKey(string dictionaryKey) { return dictionaryKey; } #endregion } 

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

 public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver { protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract contract = base.CreateDictionaryContract(objectType); contract.PropertyNameResolver = propertyName => propertyName; return contract; } } 
  • Исключение «Исключительная привязка к реляционной ссылке» с JSON.Net
  • Deserialize json с известными и неизвестными полями
  • Уничтожить stream массива json по одному элементу за раз
  • Json.Net добавляет $ id к объектам EF, несмотря на то, что PreserveReferencesHandling указывает на "None"
  • Невозможно сериализовать словарь с помощью сложного ключа с помощью Json.net
  • Удаление десериализации JSON в .NET-объект с использованием Newtonsoft (или LINQ to JSON, возможно?)
  • Как получить json.net для сериализации членов classа, полученных из List ?
  • Как игнорировать неизвестные значения enum во время десериализации json?
  • Ошибка JSON.NET Локальный цикл привязки для типа
  • Как добавить дополнительное свойство в сериализованную строку JSON с помощью json.net?
  • JsonValueProviderFactory выбрасывает «запрос слишком большой»
  • Давайте будем гением компьютера.