【问题标题】:Serialize IEnumerable<IDictionary<string, object>> doesn't work with DefaultNamingStrategy序列化 IEnumerable<IDictionary<string, object>> 不适用于 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?

【问题讨论】:

    标签: c# json asp.net-mvc-4 jsonserializer


    【解决方案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; }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-27
        相关资源
        最近更新 更多