Reputation: 101
I am seeing an exception when deserializing a JSON string that contains a JSON-serialized LocalDate object (see the end of this question for the JSON snippet).
This is how I am deserializing:
var settings = new JsonSerializerSettings();
settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
var output = JsonConvert.DeserializeObject<MyObject>(json, settings);
I see this exception message:
NodaTime.Utility.InvalidNodaDataException: 'Unexpected token parsing LocalDate. Expected String, got StartObject.'
This the MyObject class:
class MyObject
{
public LocalDate Date { get; set; }
public string AnotherProperty { get; set; }
}
Here is the JSON snippet I'm trying to deserialize:
{
"Date": {
"Calendar": {
"Id": "ISO",
"Name": "ISO",
"MinYear": -9998,
"MaxYear": 9999,
"Eras": [{
"Name": "BCE"
}, {
"Name": "CE"
}]
},
"Year": 2017,
"Month": 7,
"Day": 10,
"DayOfWeek": 1,
"YearOfEra": 2017,
"Era": {
"Name": "CE"
},
"DayOfYear": 191
},
"AnotherProperty": "A string"
}
Upvotes: 3
Views: 2269
Reputation: 3678
You can use class structure like this
public class Era
{
public string Name { get; set; }
}
public class Calendar
{
public string Id { get; set; }
public string Name { get; set; }
public int MinYear { get; set; }
public int MaxYear { get; set; }
public List<Era> Eras { get; set; }
}
public class Era2
{
public string Name { get; set; }
}
public class Date
{
public Calendar Calendar { get; set; }
public int Year { get; set; }
public int Month { get; set; }
public int Day { get; set; }
public int DayOfWeek { get; set; }
public int YearOfEra { get; set; }
public Era2 Era { get; set; }
public int DayOfYear { get; set; }
}
public class RootObject
{
public Date Date { get; set; }
public string AnotherProperty { get; set; }
}
Upvotes: -1
Reputation: 101
I have figured it out now - my problem was a bad assumption on my part in the ASP.NET route handler. @L.B 's question actually got me thinking a little more.
I was assuming that the built-in JSON serializer was serializing LocalDate in MyObject correctly in this example:
[HttpGet("myobject")]
public MyObject GetMyObject()
{
return new MyObject()
{
Date = LocalDate.FromDateTime(DateTime.Now),
AnotherProperty = "A string"
};
}
The result of this API would be the same as the JSON snippet in the question.
Calling SerializeObject
and passing settings
in, for every API handler is not a good idea either because I lose the object return type on every route handler I have.
To ensure that LocalDate
gets serialized correctly in every handler, I do the following in the ConfigureServices
method of the Startup
class:
services.AddMvc().AddJsonOptions(options =>
{
// NodaConverters lives in the NodaTime.Serialization.JsonNet assembly
options.SerializerSettings.Converters.Add(NodaConverters.LocalDateConverter);
});
Now when I call the above API, LocalDate
is serialized correctly, like this:
{
"Date":"2017-07-10",
"AnotherProperty":"A string"
}
This is the format that the DeserializeObject is also expecting.
Upvotes: 6