2016-12-17 98 views
2

我正在嘗試編寫一個自定義合約解析器,該解析器在Newtonsoft.Json.Serialization中擴展DefaultContractResolver,目的是將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 ,並且DefaultContractResolver中的CreateProperty方法沒有運氣。所有這些都跳過expando對象中的子屬性。有誰知道我需要重寫DefaultContractResolver中的什麼方法來將Expando中的子屬性名稱轉換爲PascalCase?

回答

1

ExpandoObject沒有通過反射序列化,因此修改CreateProperty將不起作用。相反,它被序列化爲IDictionary<string, object>。因此,您可以利用Json.NET 9.0.1中新增的NamingStrategy類型來創建自定義命名策略,以僅爲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" 
    } 
}