我只想为我的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服务的配置或参数设置在运行时应该序列化哪些字段,类似于以下示例:
使用JSON.net,当在基类上下文中使用时,如何防止序列化派生类的属性?
http://json.codeplex.com/discussions/347610
您有几个选项:
- 创建一个由自定义格式化程序处理的自定义类型。这个自定义类型可以(以某种方式)指定需要序列化的字段(然后将这些信息输入Json序列化程序)
- 查看每个控制器的配置(请参阅此处),尝试根据需要设置格式化程序
我最终使用了一个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))]
不过,这似乎是一个破解,我认为我应该使用契约解析器来获得要序列化的属性列表,而不是直接使用反射,但我不确定如何。
我会尝试创建这样的
public class MyJsonFormatter : JsonMediaTypeFormatter
{
public override bool CanWriteType(Type type)
{
return type == typeof(MyClass);
}
}
然后将其插入格式化程序集合的开头