问题描述
I'm trying to parse JSON file where dates are defined as JavaScript objects :
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
so I did try to parse it with the JavaScriptDateTimeConverter
test.json:
{"data" : [{"Date" : new Date(2015, 06, 01, 00, 00, 00)}]}
c#:
using (StreamReader file = File.OpenText(@"c: est.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new JavaScriptDateTimeConverter());
Rootobject deserializedRoot = (Rootobject)serializer.Deserialize(file, typeof(Rootobject));
}
Unfortunatly I'm receiving this error :
Unexpected token parsing date. Expected EndConstructor, got Integer. Path 'data[0].Date1', line 13, position 30.
From my understanding JSON.Net expect at best a new Date(52231943)
but doesn't handle constructor overloads of Javascript Date() object.
Is there any known way to convert the new Date(year, month, day)
?
You could create your own subclass of JavaScriptDateTimeConverter.cs
like so:
public class JavaScriptYMDDateTimeConverter : JavaScriptDateTimeConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);
bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
var token = JToken.Load(reader);
if (token == null || token.Type == JTokenType.Null)
{
if (!isNullable)
throw new JsonSerializationException(string.Format("Null value for type {0} at path {1}", objectType.Name, reader.Path));
return null;
}
if (token.Type != JTokenType.Constructor)
{
throw new JsonSerializationException(string.Format("Invalid Date constructor "{0}" at path {1}", token.ToString(), reader.Path));
}
var constructor = (JConstructor)token;
if (!string.Equals(constructor.Name, "Date", StringComparison.Ordinal))
{
throw new JsonSerializationException(string.Format("Invalid Date constructor "{0}" at path {1}", token.ToString(), reader.Path));
}
var values = constructor.Values().ToArray();
if (values.Length == 0)
{
throw new JsonSerializationException(string.Format("Invalid Date constructor "{0}" at path {1}", token.ToString(), reader.Path));
}
else if (values.Length == 1)
{
// Assume ticks
using (var subReader = constructor.CreateReader())
{
while (subReader.TokenType != JsonToken.StartConstructor)
subReader.Read();
return base.ReadJson(subReader, objectType, existingValue, serializer); // Use base class to convert
}
}
else
{
var year = (values.Length > 0 ? (int)values[0] : 0);
var month = (values.Length > 1 ? (int)values[1] : 0) + 1; // c# months go from 1 to 12, JavaScript from 0 to 11
var day = (values.Length > 2 ? (int)values[2] : 0);
var hour = (values.Length > 3 ? (int)values[3] : 0);
var min = (values.Length > 4 ? (int)values[4] : 0);
var sec = (values.Length > 5 ? (int)values[5] : 0);
var ms = (values.Length > 6 ? (int)values[6] : 0);
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
// Note: Where Date is called as a constructor with more than one argument, the specifed arguments represent local time.
var dt = new DateTime(year, month, day, hour, min, sec, ms, DateTimeKind.Local);
if (type == typeof(DateTimeOffset))
return new DateTimeOffset(dt);
return dt;
}
}
}
Here ReadJson()
loads the token into a JConstructor
, checks that the constructor name is Date
, then parses the children.
Note I did not override WriteJson
, so this converter will write in the same style as JavaScriptDateTimeConverter
, with the ticks appearing as the single argument to the constructor.
Use it in place of JavaScriptDateTimeConverter()
.
这篇关于如何使用 JSON.Net 转换新的日期(年、月、日)重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!