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