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

4

Consider the following class:

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实现这一目标的推荐方法?

除了编写自定义的JsonConverter并使用这些JsonConverter装饰属性之外,没有其他方法。然而,这引出了一个问题:格式处理不应该在UI层完成吗? - yorah
实际上,似乎有一种方法可以在不编写自定义转换器的情况下完成它,请参见以下内容。 - yorah
我的意思是:通过编写一个自定义转换器,并通过合同解析器将其分配给属性。 - yorah
1个回答

2
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 转换器与我们自定义的 DateTimeFormat 关联到我们的日期时间,使用 DisplayFormat 属性中指定的格式。

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

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

5
在这里你不需要自定义转换器;在你的解析器中,只需使用“IsoDateTimeConverter”并设置其上的“DateTimeFormat”。 - Brian Rogers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接