Значения словаря верблюжьего слова, но не ключи в результате Serialized из C # Web API [дубликат]

Я думаю, что mattingly890 имеет правильный ответ, вот еще один пример наряду с шаблоном / commmand

db.collection.find( {}, {your_key:1, _id:0})

enter image description here [/g0]

63
задан Soner Gönül 10 June 2014 в 15:10
поделиться

4 ответа

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

Я вижу, что вы уже используете CamelCasePropertyNamesContractResolver. Если вы выведете из этого новый класс распознавателя и переопределите метод 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 = "<html></html>",
            Dictionary = new Dictionary<string, string>
            {
                { "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<string, string> Dictionary { get; set; }
}

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

{
  "anIntegerProperty": 42,
  "htmlString": "<html></html>",
  "dictionary": {
    "WHIZbang": "1",
    "FOO": "2",
    "Bar": "3"
  }
}
102
ответ дан James Newton-King 27 August 2018 в 21:02
поделиться

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

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

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

Примечания:

  • Текущая реализация CamelCasePropertyNamesContractResolver также указывает, что .Net-члены с явно указанными именами свойств (например, те, где JsonPropertyAttribute.PropertyName установлены) должны иметь свои имена повторно:
    public CamelCasePropertyNamesContractResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }
    
    Выше resolver сохраняет это поведение. Если вы этого не хотите, установите OverrideSpecifiedNames = false.
  • Json.NET имеет несколько встроенных стратегий именования, включая: CamelCaseNamingStrategy . Стратегия именования случаев верблюда, которая содержит логику переопределения имен, ранее встроенную в CamelCasePropertyNamesContractResolver. SnakeCaseNamingStrategy . Стратегия именования змеи . DefaultNamingStrategy . Стратегия именования по умолчанию. Имена свойств и словарные ключи не изменяются. Или вы можете создать свой собственный, наследуя от абстрактного базового класса NamingStrategy.
  • Хотя также возможно изменить NamingStrategy экземпляра CamelCasePropertyNamesContractResolver , поскольку последний делится информацией о контракте во всех экземплярах каждого типа , это может привести к неожиданным побочным эффектам, если ваше приложение пытается использовать несколько экземпляров CamelCasePropertyNamesContractResolver. Нет такой проблемы с DefaultContractResolver, поэтому ее безопаснее использовать, когда требуется любая настройка логики корпуса.
44
ответ дан dbc 27 August 2018 в 21:02
поделиться

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

class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
    {
        #region Overrides of DefaultContractResolver

        protected override string ResolveDictionaryKey(string dictionaryKey)
        {
            return dictionaryKey;
        }

        #endregion
    }
11
ответ дан Dmitriy 27 August 2018 в 21:02
поделиться

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

public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
    {
        protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
        {
            JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
            contract.PropertyNameResolver = propertyName => propertyName;
            return contract;
        }
    }
0
ответ дан Sep 27 August 2018 в 21:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: