序列化 IEnumerable<IDictionary<string, object>> 不适用于 DefaultNamingStrategy

Posted

技术标签:

【中文标题】序列化 IEnumerable<IDictionary<string, object>> 不适用于 DefaultNamingStrategy【英文标题】:Serialize IEnumerable<IDictionary<string, object>> doesn't work with DefaultNamingStrategy 【发布时间】:2018-08-05 23:23:18 【问题描述】:

默认情况下,我在项目中使用 CamelCasePropertyNamesContractResolver 序列化为 json。但我想为一个属性更改此策略。

public class ViewTable

    public int Id  get; set; 

    [JsonProperty(NamingStrategyType = typeof(DefaultNamingStrategy), ItemTypeNameHandling = TypeNameHandling.None, TypeNameHandling = TypeNameHandling.None)]
    public IEnumerable<IDictionary<string, object>> Rows  get; set; 

所以当我序列化这个对象时,我希望得到这样的 json:

"result": 
    "id": 15,
    "rows": [
      
        "SessionData_Department": "",
        "SystemData_SerialNumber": "1"
      
    ]

但我得到了:

"result": 
    "id": 15,
    "Rows": [   //There must be a lowercase!!!
      
        "sessionData_Department": "", //There must be a uppercase!!!
        "systemData_SerialNumber": "1"
      
    ]

我的项目中有这样的json设置:

    var settings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
    settings.Formatting = Formatting.Indented;
    settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    settings.TypeNameHandling = TypeNameHandling.Auto;

如何告诉 json 序列化程序使用 DefaultNamingStrategy 作为 IDictionary?

【问题讨论】:

【参考方案1】:

我不确定是否有开箱即用的设置。但是您可以通过扩展JsonConverter 并使用DefaultContractResolver 来做到这一点:

public class RowsConverter : JsonConverter

    public override bool CanConvert(Type objectType)
    
        throw new NotImplementedException();
    

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        throw new NotImplementedException();
    

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        var settings = new JsonSerializerSettings()
        
            ContractResolver = new DefaultContractResolver()
        ;
        writer.WriteRawValue(JsonConvert.SerializeObject(value, settings));
    

然后将Rows属性改为:

[JsonProperty(ItemConverterType = typeof(RowsConverter))]
public IEnumerable<IDictionary<string, object>> Rows  get; set; 

【讨论】:

【参考方案2】:

你必须扩展DefaultNamingStrategy:

public class CamelCaseDictionaryKeyNamingStrategy : DefaultNamingStrategy

    public CamelCaseDictionaryKeyNamingStrategy() : 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)  [0] = char.ToUpperInvariant(key[0]) ;
                return builder.ToString();
            
        
        return key;
    

然后像这样使用它:

IDictionary<string, object> idict = new Dictionary<string, object>();

idict.Add("sessionData_Department", "1");
idict.Add("systemData_SerialNumber", "1");

IEnumerable<IDictionary<string, object>> row = new List<IDictionary<string, object>>  idict ;


var val = new ViewTable

    Id = 15,
    Rows = row
;
var cc = new CamelCasePropertyNamesContractResolver

    NamingStrategy = new CamelCaseDictionaryKeyNamingStrategy()
;


JsonSerializerSettings config = new JsonSerializerSettings

    Formatting = Formatting.Indented,
    ContractResolver = cc,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    TypeNameHandling = TypeNameHandling.Auto
;
string js = JsonConvert.SerializeObject(val, config);

输出:

我已将Rows 更新为:

public class ViewTable

    public int Id  get; set; 

    [JsonProperty(PropertyName = "rows", NamingStrategyType = typeof(DefaultNamingStrategy), ItemTypeNameHandling = TypeNameHandling.None, TypeNameHandling = TypeNameHandling.None)]
    public IEnumerable<IDictionary<string, object>> Rows  get; set; 

【讨论】:

以上是关于序列化 IEnumerable<IDictionary<string, object>> 不适用于 DefaultNamingStrategy的主要内容,如果未能解决你的问题,请参考以下文章

具有 IEnumerable<ISomeInterface> 类型属性的 NewtonSoft.Json 序列化和反序列化类

JSON反序列化是否为IEnumerable 产生结果?

是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]

IEnumerable,IQueryable之前世今生

如何标记 List 或 IEnumerable 可序列化?

译使用 LINQ 合并 IEnumerable 序列