7

我想为我的 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

4

3 回答 3

4

你有几个选择:

  • 创建由自定义格式化程序处理的自定义类型。这种自定义类型可以(以某种方式)指定需要序列化的字段(然后将该信息输入到 Json 序列化程序中)
  • 查看每个控制器配置(请参阅此处)以尝试根据需要设置格式化程序
于 2012-09-20T08:45:15.497 回答
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))]

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

于 2012-09-24T21:04:45.343 回答
0

我会尝试创建这样的东西

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

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

于 2012-09-20T12:46:11.160 回答