0

User can enter dates in a format using / or - as a separator.

The following try block works for / but fails for - and vice versa:

Try
{
    caseData.AddRange(
        JsonConvert.DeserializeObject<List<CaseInfo>>(
                jObject["caseData"].ToString(), 
                new JsonSerializerSettings { DateFormatString = "d/M/yyyy" }));
}
Catch(Exception)
{

    caseData.AddRange(
        JsonConvert.DeserializeObject<List<CaseInfo>>(
            jObject["caseData"].ToString(), 
            new JsonSerializerSettings  { DateFormatString = "d-M-yyyy" }));

}
Kjartan
  • 18,591
  • 15
  • 71
  • 96
Rahul Chavan
  • 480
  • 3
  • 6
  • You should avoid catching meaningless exceptions https://stackoverflow.com/a/1722991/3478025. In your scenario I would just add a check if case data contains '-' or '/' and then perform correct parsing – Hubert Oct 10 '19 at 05:42

2 Answers2

2

Short answer: No.

A try-catch structure is pretty expensive in terms of resources. From a design point of view, it feels wrong too; an exception should be just that: an exception - something unusual, probably an error. The way you are using it here is just to check which of two valid formats to use.

In essence, what you are doing here is using exception handling as a computationally expensive if-else operation.

A better solution might be to try to extract the contents of jObject["caseData"] first, and check it's format explicitly to know which option to use. Once you know that, you can use a regular if-else structure to decide how to deserialize it.

Something like:

var dateText = jObject["caseData"].ToString();
var matchingFormat = dateText.Contains("/") ? "d/M/yyyy" : "d-M-yyyy";

caseData.AddRange(
    JsonConvert.DeserializeObject<List<CaseInfo>>(
        jObject["caseData"].ToString(), 
        new JsonSerializerSettings  { DateFormatString = matchingFormat }));

Note: This assumes you are reasonably sure you can trust that the input will be in one of the two formats. You might want to add some more validation, especially if the date field is something that end-users can manipulate freely.

Kjartan
  • 18,591
  • 15
  • 71
  • 96
  • As my object contains entire list in JSON format, I will not be check individual fields. If there any way I can identity and process these data. – Rahul Chavan Oct 10 '19 at 08:05
  • Ah, ok, so `DeserializeObject(...)` will deserialize the whole thing in a single operation? Ofcourse, I did not realize that. Still, your original code indicates that all dates must be in the same format. That should mean that you could e.g. fetch the first item from your JSON object, and check that single object explicitly (deserialized as a `CaseInfo` if I'm not mistaken?). Once you've decided on the format based on that, you will know how to deserialize the whole list correctly. – Kjartan Oct 10 '19 at 08:22
1

What @Kjartan said plus the following.

The DateFormatString solution may not work well if you have multiple date fields and the user inputs multiple dates in different formats.

Here are some options that I you could consider, all with pros and cons:

  1. Have separate fields for year, month and day for each date;
  2. Make the API accept only dates in a given format and make the provider of the source json deal with this;
  3. Pre-parse the source data and format all dates;
  4. Make CaseInfo store dates as string and provide accessors which make the conversion;
  5. Create a custom JsonConverter, maybe based on DateTimeConverterBase, and mark your problematic properties with [JsonConverter(typeof(MyResilientDataFormatJsonConverter))].

General note: Parsing dates gets difficult quickly if you support multiple formats and/or cultures. For example: Is today 10/09/2019 or 09/10/2019?

tymtam
  • 31,798
  • 8
  • 86
  • 126