Подтвердить что ты не робот

Десерлизация свойств без учета регистра Json.NET

Json.NET перечисляет "десериализацию нечувствительности к регистру" как одну из рекламируемых функций. Я прочитал, что сначала будет сделана попытка сопоставить случай указанного свойства и если совпадение не найдено, выполняется поиск без учета регистра. Однако это не похоже на поведение по умолчанию. См. Следующий пример:

var result =
    JsonConvert.DeserializeObject<KeyValuePair<int, string>>(
        "{key: 123, value: \"test value\"}"
    );

// result is equal to: default(KeyValuePair<int, string>)

Если строка JSON изменена в соответствии со случаем свойств ( "Key" и "Value" vs "key" и "value" ), то все хорошо:

var result =
    JsonConvert.DeserializeObject<KeyValuePair<int, string>>(
        "{Key: 123, Value: \"test value\"}"
    );

// result is equal to: new KeyValuePair<int, string>(123, "test value")

Есть ли способ выполнить для десериализации нечувствительности к регистру?

4b9b3361

Ответ 1

Это ошибка.

десериализация дескрипции нечувствительности к регистру относится к Json.NET, способному сопоставлять свойство JSON с именем "Key" либо с классом .NET, либо с ключом "ключ".

Ошибка: KeyValuePair требует своего JsonConverter, но пропускает нечувствительное к регистру отображение.

https://github.com/JamesNK/Newtonsoft.Json/blob/fe200fbaeb5bad3852812db1e964473e1f881d93/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs

Используйте это как базу и добавьте строчный "ключ" и "значение" в оператор case при чтении JSON.

Ответ 2

Одним из эффективных способов я нашел использование GetValue с параметром StringComparer.

Итак, например,

JObject contact;
String strName = contact.GetValue('Name');

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

JObject contact;
String strName = contact.GetValue("ObjType", StringComparison.InvariantCultureIgnoreCase);

Ответ 3

Вы можете использовать собственный распознаватель Контракта для имени входящего свойства, которое вы можете изменить для входящего свойства в предпочтительный формат, который будет соответствовать формату свойства вашего класса объектов С#. Я сделал три пользовательских обработчика контрактов, которые изменят имя входящего свойства на Заголовок/Строчные/Верхний регистр:

public class TitleCaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        //Change the incoming property name into Title case
        var name = string.Concat(propertyName[0].ToString().ToUpper(), propertyName.Substring(1).ToLower());
        return base.ResolvePropertyName(name);
    }
}

public class LowerCaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        //Change the incoming property name into Lower case
        return base.ResolvePropertyName(propertyName.ToLower());
    }
}

public class UpperCaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        //Change the incoming property name into Upper case
        return base.ResolvePropertyName(propertyName.ToUpper());
    }
}

Затем создайте новый объект JsonSerializerSetting и поместите свой пользовательский определитель контрактов в свойство ContractResolver. Затем добавьте объект JsonSerializerSetting во второй параметр в JsonConvert.DeserializeObject(json, jsonSerializerSetting)

        var serializerSetting = new JsonSerializerSettings()
        {
            ContractResolver = new TitleCaseContractResolver()
        };
        var result = JsonConvert.DeserializeObject<YourType>(msg, serializerSetting);