1

is there any way to convert date read from JSON file? Exemplary record from my file is:

{
    "UserID": 73274,
    "Created": "17-03-2018 06:35",
    "Office": "Washington"
},

What I am doing is importing JSON file and save its content to database. The problem is, when date is in DD-MM-YYYY hh:ss format, it simply doesn't work. But when date is in YYYY-MM-DDThh:mm:ss format, everything is fine. How to parse date to another format after reading this file and execute following operations on file with parsed date?

Part of my controller responsible for this operations is:

if (file.ContentType == "application/json")
{
    try
    {
        using (var reader = new StreamReader(file.OpenReadStream()))
        {
            content = reader.ReadToEnd();
        }
     }
     catch
     {
         return BadRequest(Messages.fileNotChosen);
     }
     try
     {
         userObjects = JsonConvert.DeserializeObject<List<UserImportModel>>(content);
     }
     catch
     {
         return BadRequest();
     }
 }

When date format is YYYY-MM-DDThh:mm:ss, userObjects is properly counted and controller moves to part where I execute adding to database. When date format is DD-MM-YYYY hh:ss, userObjects = 0 and controller moves to catch, which then returns BadRequest().

EDIT: Code of UserImportModel class:

public class UserImportModel
{

    public string UserID { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
    public DateTime Created { get; set; }

    public string Office { get; set; }

}
3
  • possible duplicate of this question Commented Sep 10, 2018 at 12:56
  • 1
    There's a solution here for Json.Net if the format is fixed: stackoverflow.com/questions/21256132/… But if you have a mix of date formats then you may need to deserialise the string manually. Commented Sep 10, 2018 at 12:58
  • Imho an XY Problem. You should always pass and return your date as ISO dates, since you don't necessarily know the users globalization settings. The UI (WPF, WinForms, HTML/JavaScript, Angular etc) should take that ISO time (it contains time zone information and more) and show it in the users language format and time zone Commented Sep 10, 2018 at 14:37

2 Answers 2

2

If you need to deserialize date in different formats, you have to create a custom JsonConverter:

public class MultiFormatDateTimeConverter : JsonConverter
{
    private List<string> formats;

    public MultiFormatDateTimeConverter(List<string> formats)
    {
       this.formats = formats;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string dateString = (string)reader.Value;

        foreach (string format in formats)
        {
            if (DateTime.TryParseExact(dateString, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
            {
                return date;
            }
        }
        throw new JsonException("Unable to parse \"" + dateString + "\" as a date.");
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Usage example:

var settings = new JsonSerializerSettings();
settings.DateParseHandling = DateParseHandling.None;
settings.Converters.Add(new MultiFormatDateTimeConverter(new List<string> { "DD-MM-YYYY hh:ss", "YYYY-MM-DDThh:mm:ss" }));

userObjects = JsonConvert.DeserializeObject<List<UserImportModel>>(content, settings);
Sign up to request clarification or add additional context in comments.

1 Comment

Your solution did the job. It also allows me to specify many date formats to be converted to ISO8601 standard, so I will stick to it. Thank you very much.
1

JSON.Net uses the Standard 8601 to represent Date-Time. The extended format for a complete date-time expression is: "YYYY-MM-DDTHH:MM:SS". The JSON.Net "Deserializer" method (DeserializeObject) is overloaded for acceptting custom formatters, you can use de IsoDateTimeConverter specifying in the DateTimeFormat property the format of your string "dd"

userObjects = JsonConvert.DeserializeObject<List<UserImportModel>>(content, 
                   new IsoDateTimeConverter { DateTimeFormat = "dd-MM-yyyy hh:mm:ss" });

Another alternative is to use a regular expresion to replace all bad formed ISO Dates in your JSON string before calling the DeserializeObject method.

1 Comment

I tried to use IsoDateTimeConverter as I found similar solution in other thread, but it didn't work for me. Turned out I specified in DateTimeFormat property format of date that I wanted to have instead one I had in my JSON file. What a shame. Using regular expressions is also good idea if everything other fails.

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.