覆盖Json.NET属性序列化/格式化

时间:2014-04-04 09:35:36

标签: c# json.net

考虑以下课程:

public class Person
{
    [DisplayFormat(DataFormatString = "dd/MM/yyyy")]
    public DateTime DOB { get; set; }
}

当使用Json.NET将对象序列化为JSON时,如果属性使用DisplayFormatAttribute进行修饰,我希望覆盖序列化。这应该有效地呼吁:

object toBeSerialized = DOB.ToString(attribute.DateFormatString)

有效地返回格式化字符串而不是DateTime

使用Json.NET实现此目的的推荐方法是什么?

1 个答案:

答案 0 :(得分:3)

JsonConverter类无权访问属性声明,因此无法获取它所装饰的属性。

此外,无法使用自定义JsonConverter装饰您的属性,并将其传递给您要使用的日期格式,因为您应该传递类型你想要使用的JsonConverter,而不是实例:

// This doesn't help us...
[JsonConverter(typeof(CustomDateTimeFormatConverter)]
public DateTime DOB { get; set; }

那我们该怎么做?

为了将格式字符串传递给我们的转换器,我们可以通过以下ContractResolver(通过反射访问属性信息)将其关联起来:

public class CustomDateTimeFormatResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        // skip if the property is not a DateTime
        if (property.PropertyType != typeof (DateTime))
        {
            return property;
        }

        var attr = (DisplayFormatAttribute)member.GetCustomAttributes(typeof(DisplayFormatAttribute), true).SingleOrDefault();
        if (attr != null)
        {
            var converter = new IsoDateTimeConverter();
            converter.DateTimeFormat = attr.DataFormatString;
            property.Converter = converter;
        }

        return property;
    }
}

这将使用IsoDateTimeConverter属性中指定的格式将DisplayFormat转换器与我们的自定义DateTimeFormat关联到运行时的日期时间。

为了告诉Json.NET使用我们的ContractResolver,我们需要在序列化为json时使用这种语法:

string json = JsonConvert.SerializeObject(
            p, Formatting.Indented,
            new JsonSerializerSettings
                { ContractResolver = new CustomDateTimeFormatResolver() });