如何为特定类型而不是全局设置Json.NET ContractSerializer?

时间:2012-09-19 19:46:51

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

我想在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

3 个答案:

答案 0 :(得分:4)

您有几个选择:

  • 创建由自定义格式化程序处理的自定义类型。此自定义类型可以指定(以某种方式)需要序列化的字段(然后将该信息提供给Json序列化程序)
  • 查看每个控制器配置(请参阅here)以尝试将格式化程序设置为requried

答案 1 :(得分:1)

我最终使用的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))]

这看起来像是一个黑客,我想我应该使用合约解析器获取序列化的属性列表而不是直接使用反射,但我不确定如何。

答案 2 :(得分:0)

我会尝试创建这样的东西

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

然后将其插入到formatters集合的开头