【问题标题】:How to set Json.NET ContractSerializer for a certain specific type instead of globally?如何为某个特定类型而不是全局设置 Json.NET ContractSerializer?
【发布时间】:2012-09-19 19:46:50
【问题描述】:

我想为我的 ASP.NET Web API 应用程序中的某些类型设置一个合同序列化程序。我可以像这样在 App_Start/FormatterConfig.cs 中全局设置设置:

public static void RegisterGlobalFormatters(MediaTypeFormatterCollection formatters)
{
    jsonSerializerSettings.ContractResolver = new CriteriaContractResolver(new List<string>(new string[]{"mdData", "name", "label"})); 

...

但是我怎样才能将它应用到一个或多个特定的类类型呢?

我想这样做的原因是因为我需要能够根据 Web 服务的配置或参数设置在运行时应该序列化哪些字段,类似于这些示例:

Using JSON.net, how do I prevent serializing properties of a derived class, when used in a base class context?

http://json.codeplex.com/discussions/347610

【问题讨论】:

    标签: c# asp.net-web-api json.net


    【解决方案1】:

    你有几个选择:

    • 创建由自定义格式化程序处理的自定义类型。这种自定义类型可以(以某种方式)指定需要序列化哪些字段(然后将该信息输入到 Json 序列化程序中)
    • 查看每个控制器配置(请参阅here)以尝试根据需要设置格式化程序

    【讨论】:

    • 您的第一个选项让我制作了一个比格式化程序更低级别的自定义 JsonConverter,但我不知道如何为特定类型指定格式化程序。
    【解决方案2】:

    我最终使用了只写入“属性”列表中指定的参数的 JsonConverter。它比 ContractResolver 或格式化程序更低级别,但我认为不可能为特定类型配置任何一个。

    public class ResourceConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(Resource));
        }
    
        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)
        {
            List<string> properties = new List<string>(new string[] { "Name", "Label" });
    
            writer.WriteStartObject();
            foreach (MemberInfo mi in value.GetType().GetMembers(BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public) )
            {
                PropertyInfo p = mi as PropertyInfo;
    
                if (p != null && p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length == 0 && properties.Contains(p.Name))
                {
                    writer.WritePropertyName(p.Name);
                    serializer.Serialize(writer, p.GetValue(value, new object[] { }));
                }
            }
            writer.WriteEndObject();
        }
    }
    

    这可以使用属性应用于类:

    [JsonConverter(typeof(ResourceConverter))]
    

    虽然这似乎是一个 hack,但我认为我应该使用合约解析器来获取要序列化的属性列表,而不是直接使用反射,但我不确定如何。

    【讨论】:

      【解决方案3】:

      我会尝试创建类似的东西

      public class MyJsonFormatter : JsonMediaTypeFormatter
          {
              public override bool CanWriteType(Type type)
              {
                  return type == typeof(MyClass);
              }
          }
      

      然后将其插入到格式化程序集合的开头

      【讨论】:

      • 它似乎只根据正在序列化的根对象的类型为每个请求选择一次格式化程序。在我的情况下它不起作用,因为我有一个我不想将设置应用到的包装对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 2021-10-26
      相关资源
      最近更新 更多