如何从.NET数据结构创建“锯齿状”对象的JSON数组
作为LINQ-to-Entities投影的结果,我最终得到了一个List
,如下所示,我手动创建它:
List data = new List(); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g0", value = 70 }); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g1", value = 60 }); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g2", value = 100 }); data.Add(new ChartDataRecord { date = 1370563260000, graph = "g0", value = 71 }); data.Add(new ChartDataRecord { date = 1370563260000, graph = "g2", value = 110 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g0", value = 72 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g1", value = 62 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g2", value = 150 });
我正在使用的图表框架(amCharts)要求JSON数据提供程序的格式如下:
{ "data": [ { "date": 1370563200000, "g0": 70, "g1": 60, "g2": 100 }, { "date": 1370563260000, "g0": 71, "g2": 110 }, { "date": 1370563320000, "g0": 72, "g1": 62, "g2": 150 } ], ...other chart properties }
将样本List
序列化为此JSON结构的推荐方法是什么? Json.NET框架中是否有一些可以使这相当容易的东西? 如果没有,这将如何手动完成? 我是否应该为List
使用更动态的数据结构并尝试使用我的LINQ-to-Entities查询填充它?
您可以使用自定义转换器执行此操作,如下所示:
class ChartDataRecordCollectionConverter : JsonConverter { /// /// Writes the JSON representation of the object. /// /// The to write to.The value.The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var set = (ChartDataRecordCollection) value; writer.WriteStartObject(); writer.WritePropertyName("data"); writer.WriteStartArray(); //Group up the records in the collection by the 'date' property foreach (var record in set.GroupBy(x => x.date)) { writer.WriteStartObject(); writer.WritePropertyName("date"); writer.WriteValue(record.Key); //Write the graph/value pairs as properties and values foreach (var part in record) { writer.WritePropertyName(part.graph); writer.WriteValue(part.value); } writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteEndObject(); } /// /// Reads the JSON representation of the object. /// /// The to read from.Type of the object.The existing value of object being read.The calling serializer. /// /// The object value. /// public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var result = new ChartDataRecordCollection(); var obj = JObject.Load(reader); var container = obj["data"]; //Examine each object in the array of values from the result foreach (JObject item in container) { //Get and store the date property var date = item["date"].Value(); //For each property that is not the date property on the object, construct a // ChartDataRecord with the appropriate graph/value pair foreach (var property in item.Properties()) { if (property.Name == "date") { continue; } result.Add(new ChartDataRecord { date = date, graph = property.Name, value = item[property.Name].Value() }); } } return result; } /// /// Determines whether this instance can convert the specified object type. /// /// Type of the object. /// /// true if this instance can convert the specified object type; otherwise, false . /// public override bool CanConvert(Type objectType) { return objectType == typeof (ChartDataRecordCollection); } }
此转换器将对包含List
的集合类型进行操作,如此定义
[JsonConverter(typeof(ChartDataRecordCollectionConverter))] public class ChartDataRecordCollection : List { public ChartDataRecordCollection() { } public ChartDataRecordCollection(IEnumerable records) { AddRange(records); } }
用法示例(和正确性certificate):
public class ChartDataRecord { public long date { get; set; } public string graph { get; set; } public int value { get; set; } public override bool Equals(object obj) { var o = (ChartDataRecord) obj; return o.date == date && o.graph == graph && o.value == value; } } ... static void Main(string[] args) { var data = new List { new ChartDataRecord { date = 1370563200000, graph = "g0", value = 70 }, new ChartDataRecord { date = 1370563200000, graph = "g1", value = 60 }, new ChartDataRecord { date = 1370563200000, graph = "g2", value = 100 }, new ChartDataRecord { date = 1370563260000, graph = "g0", value = 71 }, new ChartDataRecord { date = 1370563260000, graph = "g2", value = 110 }, new ChartDataRecord { date = 1370563320000, graph = "g0", value = 72 }, new ChartDataRecord { date = 1370563320000, graph = "g1", value = 62 }, new ChartDataRecord { date = 1370563320000, graph = "g2", value = 150 } }; var records = new ChartDataRecordCollection(data); var result = JsonConvert.SerializeObject(records); Console.WriteLine(result); var test = JsonConvert.DeserializeObject(result); Console.WriteLine(records.SequenceEqual(test)); Console.ReadLine(); }
输出:
{"data":[{"date":1370563200000,"g0":70,"g1":60,"g2":100},{"date":1370563260000,"g0":71,"g2":110},{"date":1370563320000,"g0":72,"g1":62,"g2":150}]} true
是的,JSON.NET可以很容易地处理它。 只需将列表添加到另一个对象的“data”属性中,然后对其进行序列化。 下面的示例对“包装器”对象使用匿名类型,但“正常”CLR类型也可以正常工作。
public class StackOverflow_17012831 { public class ChartDataRecord { public long date { get; set; } public string graph { get; set; } public int value { get; set; } } public static void Test() { List data = new List (); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g0", value = 70 }); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g1", value = 60 }); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g2", value = 100 }); data.Add(new ChartDataRecord { date = 1370563260000, graph = "g0", value = 71 }); data.Add(new ChartDataRecord { date = 1370563260000, graph = "g2", value = 110 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g0", value = 72 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g1", value = 62 }); data.Add(new ChartDataRecord { date = 1370563320000, graph = "g2", value = 150 }); var obj = new { data = data, name = "Name" }; string str = JsonConvert.SerializeObject(obj); Console.WriteLine(str); } }