Расширение DefaultContractResolver для преобразования подсвойств ExpandoObject в PascalCase

Я пытаюсь написать собственный сопоставитель контрактов, который расширяет DefaultContractResolver в Newtonsoft.Json.Serialization с целью преобразования всех свойств в ExpandoObject с именами свойств PascalCase.

Мой контракт:

public class Fruit 
{
    public int Id { get; set; }
    public ExpandoObject FruitProperties { get; set; }
}

Я передаю следующие данные:

{
  "Id": "1234",
  "FruitProperties" : {
      "colour": "red",
      "Taste": "sweet
   }

  }

}

Результат, который я ожидаю, следующий:

{
   "Id": "1234",
   "FruitProperties" : {
      "Colour": "red",
      "Taste": "sweet"
    }
}

Я безуспешно пытался переопределить методы ResolvePropertyName и CreateProperty в DefaultContractResolver. Все они пропускают вложенные свойства в объекте Expando. Кто-нибудь знает, какой метод в DefaultContractResolver мне нужно переопределить, чтобы преобразовать имена подсвойств в Expando в PascalCase?


person Msgm    schedule 17.12.2016    source источник


Ответы (1)


ExpandoObject не сериализуется посредством отражения, поэтому изменение CreateProperty не сработает. . Скорее, он сериализуется как IDictionary<string, object>. Таким образом, вы можете воспользоваться преимуществами нового типа NamingStrategy в Json.NET 9.0.1 для создания пользовательской стратегии именования для PascalCase < em>только словарные ключи и ничего больше. NamingStrategy имеет свойство NamingStrategy.ProcessDictionaryKeys, которое, если установлено значение true, вызывает Json .NET для сопоставления имен ключей словаря:

public class PascalCaseDictionaryKeyNamingStrategy : DefaultNamingStrategy
{
    public PascalCaseDictionaryKeyNamingStrategy() : base() { this.ProcessDictionaryKeys = true; }

    public override string GetDictionaryKey(string key)
    {
        if (ProcessDictionaryKeys && !string.IsNullOrEmpty(key))
        {
            if (char.ToUpperInvariant(key[0]) != key[0])
            {
                var builder = new StringBuilder(key);
                builder[0] = char.ToUpperInvariant(key[0]);
                return builder.ToString();
            }
        }
        return key;
    }
}

Затем установите его на DefaultContractResolver.NamingStrategy (или на любом пользовательский подкласс DefaultContractResolver, если хотите):

var resolver = new DefaultContractResolver { NamingStrategy = new PascalCaseDictionaryKeyNamingStrategy() };
var json = JsonConvert.SerializeObject(fruit, Formatting.Indented, new JsonSerializerSettings { ContractResolver = resolver });

Console.WriteLine(json);

Что выводит:

{
  "Id": 1234,
  "FruitProperties": {
    "Colour": "red",
    "Taste": "sweet"
  }
}
person dbc    schedule 17.12.2016
comment
Ваш собственный класс NamingStrategy может наследоваться от NamingStrategy вместо DefaultNamingStrategy, и этот подход все равно будет работать. - person user1007074; 11.12.2018