4

Consider the following class:

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

When serializing the object to JSON with Json.NET I would like to override the serializing if the property is decorated with a DisplayFormatAttribute. This should effectively call:

object toBeSerialized = DOB.ToString(attribute.DateFormatString)

Effectively returning a formatted string instead of DateTime.

What's the recommended approach for achieving this with Json.NET?

4
  • Short of writing a custom JsonConverter for each of your format, and decorating your properties with these JsonConverter, no way. However, this leads to the question: shouldn't the format handling be done in the UI layer? Commented Apr 4, 2014 at 10:10
  • Actually, there seems to be a way to do it without writing custom converters, see below Commented Apr 4, 2014 at 10:36
  • I meant: by writing one custom converter, and assigning it to the properties through a contract resolver. Commented Apr 4, 2014 at 13:38
  • See also: Specifying a custom DateTime format when serializing with Json.Net Commented Apr 4, 2014 at 15:10

1 Answer 1

2

The JsonConverter class does not have access to the property declaration, so it has no way to get the attributes it is decorated with.

Also, there is no way to decorate your property with a custom JsonConverter, and pass it the date format you want to use, because you are supposed to pass the type of the JsonConverter you want to use, and not the instance:

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

So how can we do ?

In order to pass a format string to our Converter, we can associate it through the following ContractResolver (which has access to the property info through reflection):

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

This will associate an IsoDateTimeConverter converter with our custom DateTimeFormat to our datetime at runtime, using the format specified in the DisplayFormat attribute.

And in order to tell Json.NET to use our ContractResolver, we need to use this syntax when serializing to json:

string json = JsonConvert.SerializeObject(
            p, Formatting.Indented,
            new JsonSerializerSettings
                { ContractResolver = new CustomDateTimeFormatResolver() });
Sign up to request clarification or add additional context in comments.

1 Comment

You don't need a custom converter here; inside your resolver just use the IsoDateTimeConverter and set the DateTimeFormat on it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.