How to set Json.NET ContractSerializer for a certa

2020-07-09 08:19发布

I want to set a contract serializer just for certain types in my ASP.NET Web API application. I can set the settings globally in the App_Start/FormatterConfig.cs like this:

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

...

but how can I just apply this to one or more specific class types?

The reason I want to do this is because I need to be able to set what fields should be serialized at runtime based on configuration or parameters to the web service similar to these examples:

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条回答
甜甜的少女心
2楼-- · 2020-07-09 09:08

I would try creating something like this

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

and then insert this into the beginning of the formatters collection

查看更多
仙女界的扛把子
3楼-- · 2020-07-09 09:11

I ended up using a JsonConverter that only writes the parameters that are specified in the "properties" list. It's more low level than a ContractResolver or a formatter, but I don't think it's possible to configure either one for a specific type.

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();
    }
}

This can be applied to a class using the attribute:

[JsonConverter(typeof(ResourceConverter))]

This seems like a hack though, I think I should use the contract resolver to get the list of properties to serialize instead of using reflection directly, but I'm not sure how.

查看更多
家丑人穷心不美
4楼-- · 2020-07-09 09:18

You have a few options:

  • Create a custom type that is handled by a custom formatter. This custom type could specify (in some manner) what fields need to be serialized (and that information then fed into a Json serializer)
  • Look at per controller configuration (see here) to try and setup the formatter as requried
查看更多
登录 后发表回答