Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing Microsoft.OData.Edm.Date

I am using JsonConvert.DeserializeObject to deserialize an object, and the routine came across a date field that it did not know how to handle. Here is the error:

Error converting value \"2018-08-22\" to type 
'System.Nullable`1[Microsoft.OData.Edm.Date]'. Path 'value[3].actualclosedate'

Microsoft.OData.Edm.Date is a struct object used by Microsoft to hold date-only data.

I am trying to build a custom converter for this type of field, but not getting it to work properly.

Here is my converter code:

public class EdmDateConverter : DateTimeConverterBase
{
    public override bool CanConvert(Type objectType) { return objectType == typeof(global::Microsoft.OData.Edm.Date); }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return (global::Microsoft.OData.Edm.Date)global::Microsoft.OData.Edm.Date.Parse(reader.ReadAsString());
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        string myDate = ((global::Microsoft.OData.Edm.Date)value).Year.ToString("D4");
        myDate += "-";
        myDate += ((global::Microsoft.OData.Edm.Date)value).Month.ToString("D2");
        myDate += "-";
        myDate += ((global::Microsoft.OData.Edm.Date)value).Day.ToString("D2");

        writer.WriteValue(myDate);
    }
}

And here is how I tried to link it into the global list of converters:

JsonConvert.DefaultSettings = () =>
            {
                var settings = new JsonSerializerSettings();
                settings.Converters.Add(new EdmDateConverter());
                //settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                return settings;
            };

I am getting the same error as before, so either the converter is not getting added correctly or I don't have it written properly.

Can anyone give me some guidance on this issue?

like image 752
Bryan Hunt Avatar asked Nov 08 '22 00:11

Bryan Hunt


1 Answers

Your error message indicates that the member type being deserialized is a Nullable<Microsoft.OData.Edm.Date>, but your CanConvert method is not accounting for the possibility that objectType might be nullable.

You can fix this by modifying CanConvert as follows:

public class EdmDateConverter : DateTimeConverterBase
{
    public override bool CanConvert(Type objectType) 
    {
        var type = Nullable.GetUnderlyingType(objectType) ?? objectType;
        return type == typeof(global::Microsoft.OData.Edm.Date); 
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.SkipComments().TokenType == JsonToken.Null)
            return null;
        return (global::Microsoft.OData.Edm.Date)global::Microsoft.OData.Edm.Date.Parse(reader.ReadAsString());
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        string myDate = ((global::Microsoft.OData.Edm.Date)value).Year.ToString("D4");
        myDate += "-";
        myDate += ((global::Microsoft.OData.Edm.Date)value).Month.ToString("D2");
        myDate += "-";
        myDate += ((global::Microsoft.OData.Edm.Date)value).Day.ToString("D2");

        writer.WriteValue(myDate);
    }
}

public static partial class JsonExtensions
{
    public static JsonReader SkipComments(this JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }
}

Notes:

  • It is also necessary for check for a null token in ReadJson(). WriteJson(), on the other hand, is never called for a null value; instead Json.NET writes null automatically.

  • There may be other issues with your code since your question does not include sample JSON, deserialization code or c# classes.

like image 130
dbc Avatar answered Nov 13 '22 16:11

dbc