为Google Charts返回带有Date类型的JSON数组
本文关键字:类型 JSON 数组 Date Google Charts 返回 | 更新日期: 2023-09-27 18:09:57
我有一个来自Google Charts的' timeline '图表。当填充数据时,它需要一个JavaScript Date类型。
我的初始代码是这样的:
var container = document.getElementById('divChart1');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Name' });
dataTable.addColumn({ type: 'string', id: 'Category' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
现在我试图通过AJAX和日期类型填充它给我的问题。
需要像这样填充行:
dataTable.addRows([
['Aaa', 'A', new Date(2014, 1, 1), new Date(2016, 12, 31)],
['Bbb', 'B', new Date(2014, 1, 1), new Date(2016, 5, 31)]]);
是否有任何方法我可以返回一个序列化的集合从我的AJAX服务,只是解析它直接,或者我需要迭代集合和更新一个JavaScript日期每次?
当我尝试dataTable.addRows(JSON.parse(result.chartData));
时,我得到以下错误:Error: Type mismatch. Value 2015-08-26T11:59:23.889004+02:00 does not match type date in column index 2
为了提供信息,下面是AJAX服务的样子:
List<List<object>> chartData = new List<List<object>>();
chartData.Add(new List<object>() {
"Aaa",
"A",
DateTime.Now,
DateTime.Now.AddMonths(3)
});
return JsonConvert.SerializeObject(chartData);
edit:我已经让它工作了。仍在调整,但这是要点:
chartData.Add(new List<object>() {
"Aaa",
"A",
DateTime.Now.Year + "#" + DateTime.Now.Month + "#" + DateTime.Now.Day,
DateTime.Now.AddMonths(3).Year + "#" + DateTime.Now.AddMonths(3).Month + "#" + DateTime.Now.AddMonths(3).Day
});
var result = $.parseJSON(result.chartData);
$.each(result, function (k, v) {
var s = v[2].split('#');
var e = v[3].split('#');
dataTable.addRow([v[0], v[1], new Date(s[0], s[1], s[2]), new Date(e[0], e[1], e[2])]);
});
不打算用这个作为正式答案,因为它没有回答问题。
更新
虽然JSON是根据您原来的问题所要求创建的,但似乎JSON.parse('new Date(2014, 1, 1)')
不起作用,因为JavaScript日期构造器不是严格有效的JSON。
DateTime
序列化为字符串,并将一个恢复函数传递给JSON.parse()
,该函数识别日期字符串并构建JavaScript Date
。例如:如何解析JSON接收JavaScript中的日期对象?演示如何创建一个识别Microsoft格式日期的reviver函数。要以这种格式输出日期,请使用设置
JsonSerializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
。对于ISO日期格式的日期字符串,请参见这里的示例:JavaScript JSON日期解析和实际日期,或者这里:如何使用JSON。
原始回答
您可以扩展JavaScriptDateTimeConverter
以new Date(2014, 1, 1 [, H [, M [, S [, MS]]]])
格式写入和读取日期(我正在扩展这个只读取不写入的答案):
public class JavaScriptYMDDateTimeConverter : JavaScriptDateTimeConverter
{
public bool StripTimeOfDay { get; set; }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is DateTime)
{
// 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 date = ((DateTime)value).ToLocalTime();
writer.WriteStartConstructor("Date");
writer.WriteValue(date.Year);
writer.WriteValue(date.Month - 1);
writer.WriteValue(date.Day);
if (!StripTimeOfDay)
{
var written = date.Date;
var epsilon = new TimeSpan(TimeSpan.TicksPerMillisecond);
// Only write hours, min, sec, ms if needed.
if (date < written - epsilon || date > written + epsilon)
{
writer.WriteValue(date.Hour);
written = written.AddHours(date.Hour);
}
if (date < written - epsilon || date > written + epsilon)
{
writer.WriteValue(date.Minute);
written = written.AddMinutes(date.Minute);
}
if (date < written - epsilon || date > written + epsilon)
{
writer.WriteValue(date.Second);
written = written.AddSeconds(date.Second);
}
if (date < written - epsilon || date > written + epsilon)
{
writer.WriteValue(date.Millisecond);
written = written.AddMilliseconds(date.Millisecond);
}
}
writer.WriteEndConstructor();
}
else
{
// DateTimeOffset
base.WriteJson(writer, value, serializer);
}
}
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;
}
}
}
然后像这样使用:
var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new JavaScriptYMDDateTimeConverter { StripTimeOfDay = true } } };
return JsonConvert.SerializeObject(chartData, settings);
输出[["Aaa","A",new Date(2015,7,26),new Date(2015,10,26)]]
可以将日期放在括号中
如
{
"cols": [
{"label": "Date", "type": "date"},
{"label": "Serie 1", "type": "number"},
{"label": "Serie 2", "type": "number"},
],
"rows": [
{"c":[{"v": "Date(2014, 1, 1)"}, {"v": 1000}, {"v": 400}]},
{"c":[{"v": "Date(2014, 2, 25)"}, {"v": 1170}, {"v": 460}]},
{"c":[{"v": "Date(2014, 3, 15)"}, {"v": 660}, {"v": 1120}]},
{"c":[{"v": "Date(2014, 4, 30)"}, {"v": 1030}, {"v": 540}]},
]
}
请注意Google关于Date构造函数和浏览器的建议:https://developers.google.com/chart/interactive/docs/datesandtimes