2016-12-17 10 views
2

Я пытаюсь написать собственный распознаватель контрактов, который расширяет DefaultContractResolver в Newtonsoft.Json.Serialization, с целью преобразования всех свойств в ExpandoObject с именами свойств PascalCase.Расширение DefaultContractResolver для преобразования дополнительных свойств 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 мне нужно переопределить, чтобы преобразовать имена свойств sub в Expando в PascalCase?

ответ

1

ExpandoObject не сериализован через отражение, поэтому изменение CreateProperty не будет работать. Скорее, он сериализуется как IDictionary<string, object>. Таким образом, вы можете использовать новый тип NamingStrategy в Json.NET 9.0.1, чтобы создать собственную стратегию именования для PascalCase только словарные ключи и ничего больше. 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 (или на любом custom subclass of 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" 
    } 
}