I am running an ASP.NET Core 5 MVC project and tried to convert JSON response object from a Web API call to a list of ProductPromotionModels
:
dynamic likesResult = await response.Content.ReadAsStringAsync();
var objs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProductPromotionModel>>(likesResult.ToString());
When I run this code in my application, I get this deserializing error:
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type ‘System.TimeSpan’ because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly. To fix this error either change the JSON to a JSON primitive value
(e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path ‘$values[0].startTime.ticks’, line 1, position 287
According to error message, the issue is in the startTime
(Timespan property) property. So I have used JsonConverter
, below is the json object:
{
"$id": "1",
"$values": [
{
"startTime": {
"ticks": 36000000000,
"days": 0,
"hours": 1,
"milliseconds": 0,
"minutes": 0,
"seconds": 0,
"totalDays": 0.041666666666666664,
"totalHours": 1,
"totalMilliseconds": 3600000,
"totalMinutes": 60,
"totalSeconds": 3600
},
"endTime": {
"ticks": 36000000000,
"days": 0,
"hours": 1,
"milliseconds": 0,
"minutes": 0,
"seconds": 0,
"totalDays": 0.041666666666666664,
"totalHours": 1,
"totalMilliseconds": 3600000,
"totalMinutes": 60,
"totalSeconds": 3600
}
}
]
}
Entity class
public partial class ProductPromotionModel
{
// ...
[Display(Name = "Start Time")]
[DataType(DataType.Time)]
[JsonConverter(typeof(TimeSpanToStringConverter), null)]
public TimeSpan StartTime { get; set; }
[Display(Name = "End Time")]
[DataType(DataType.Time)]
[JsonConverter(typeof(TimeSpanToStringConverter),null)]
public TimeSpan EndTime { get; set; }
// ...
}
Converter class
public class TimeSpanToStringConverter : JsonConverter<TimeSpan>
{
public override TimeSpan ReadJson(JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int milliseconds = 0;
TimeSpan model = new TimeSpan();
if (reader.TokenType != JsonToken.StartObject)
{
throw new Newtonsoft.Json.JsonException();
}
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndObject)
{
break;
}
if (reader.TokenType == JsonToken.PropertyName)
{
string propertyName = reader.ReadAsString();
switch (propertyName)
{
case "days":
days = (int)reader.ReadAsInt32();
break;
case "hours":
hours = (int)reader.ReadAsInt32();
break;
case "milliseconds":
milliseconds = (int)reader.ReadAsInt32();
break;
case "minutes":
minutes = (int)reader.ReadAsInt32();
break;
case "seconds":
seconds = (int)reader.ReadAsInt32();
break;
default:
break;
}
}
}
if (reader.TokenType == JsonToken.EndObject)
{
model = new TimeSpan(days, hours, minutes, seconds, milliseconds);
}
return model;
}
public override void WriteJson(JsonWriter writer, TimeSpan value, Newtonsoft.Json.JsonSerializer serializer)
{
return;
}
}
When I debug the converter, Propertyname
show as numbers not the PropertyName
as below. How can I get the PropertyName
using JsonReader
?
2
Answers
When I replace the code
string propertyName = reader.ReadAsString()
bystring propertyName = reader.Value.ToString()
issue was fixed in the converter class.Also startTime and EndTime getting from Sql Time Columns as below image:
you have a wrong syntax, read as a string always returns string, also converter could be much more simple