如何使用JSON.Net转换新的Date(年,月,日)重载 [英] How to convert new Date(year, month, day) overload with JSON.Net

查看:172
本文介绍了如何使用JSON.Net转换新的Date(年,月,日)重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解析JSON文件,其中日期被定义为 JavaScript对象

  new Date(year,month [,day [,hour [,minutes [,seconds [,milliseconds]]]]] ); 

所以我试着用 JavaScriptDateTimeConverter



test.json:

  {data:[{Date:new Date(2015,06,01 00,00,00)}]} 

c#:

  {
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new JavaScriptDateTimeConverter());
Rootobject deserializedRoot =(Rootobject)serializer.Deserialize(file,typeof(Rootobject));
}

不幸的是我收到这个错误:


意外的令牌解析日期。预期的EndConstructor,得到整数。路径数据[0]。日期 1 ',第13行,第30行。 p>

从我的理解JSON.Net期望最多只有一个新的日期(52231943)没有处理Javascript Date()对象的构造函数重载。



有没有任何已知的方法来转换新的日期(年,月,日) )

解决方案

您可以创建自己的 JavaScriptDateTimeConverter.cs like so:

  public class JavaScriptYMDDateTimeConverter:JavaScriptDateTimeConverter 
{
public override object ReadJson(JsonReader reader ,type objectType,object existingValue,JsonSerializer serializer)
{
Type type =(Nullable.GetUnderlyingType(objectTy pe)​​?? 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对于类型{0}在路径{1},objectType.Name,reader.Path));
返回null;
}
if(token.Type!= JTokenType.Constructor)
{
throw new JsonSerializationException(string.Format(Invalid Date constructor \{0} \在路径{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 } \在路径{1},token.ToString(),reader.Path));
}

var values = constructor.Values()。ToArray();

if(values.Length == 0)
{
throw new JsonSerializationException(string.Format(Invalid Date constructor \{0} \ 1},token.ToString(),reader.Path));
}
else if(values.Length == 1)
{
//假设ticks
使用(var subReader = constructor.CreateReader())
{
while(subReader.TokenType!= JsonToken.StartConstructor)
subReader.Read();
return base.ReadJson(subReader,objectType,existingValue,serializer); //使用基类转换
}
}
else
{
var year =(values.Length> 0?(int)values [0] 0);
var month =(values.Length> 1?(int)values [1]:0)+ 1; // c#个月从1到12,JavaScript从0到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
//注意:将Date作为构造函数调用有多个参数,指定的参数表示本地时间。
var dt = new DateTime(年,月,日,小时,最小,秒,ms,DateTimeKind.Local);
if(type == typeof(DateTimeOffset))
返回新的DateTimeOffset(dt);
return dt;
}
}
}

这里 ReadJson()将令牌加载到 JConstructor ,检查构造函数名称 Date ,然后解析孩子。



注意我没有覆盖 WriteJson ,所以这个转换器将写入与 JavaScriptDateTimeConverter 相同的样式,其中ticks作为构造函数的单个参数。 / p>

使用它代替 JavaScriptDateTimeConverter()


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:\test.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转换新的Date(年,月,日)重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆