C# 如何从.NET数据结构创建“锯齿状”对象的JSON数组
作为LINQ到实体投影的结果,我最终得到一个列表,该列表与我手动创建的列表类似:C# 如何从.NET数据结构创建“锯齿状”对象的JSON数组,c#,json,linq-to-entities,json.net,C#,Json,Linq To Entities,Json.net,作为LINQ到实体投影的结果,我最终得到一个列表,该列表与我手动创建的列表类似: List<ChartDataRecord> data = new List<ChartDataRecord>(); data.Add(new ChartDataRecord { date = 1370563200000, graph = "g0", value = 70 }); data.Add(new ChartDataRecord { date = 1370563200000, grap
List<ChartDataRecord> data = new List<ChartDataRecord>();
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 });
将示例列表序列化到此JSON结构中的推荐方法是什么?在Json.NET框架中有什么东西可以让这变得相当容易吗?如果没有,如何手动完成?我是否应该为列表使用更动态的数据结构,并尝试使用我的LINQ to Entities查询填充它?是的,JSON.NET可以非常轻松地处理它。只需将列表添加到另一个对象的数据属性中,并将其序列化即可。下面的示例对包装器对象使用匿名类型,但普通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<ChartDataRecord> data = new List<ChartDataRecord>();
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);
}
}
是的,JSON.NET可以很容易地处理它。只需将列表添加到另一个对象的数据属性中,并将其序列化即可。下面的示例对包装器对象使用匿名类型,但普通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<ChartDataRecord> data = new List<ChartDataRecord>();
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);
}
}
您可以使用自定义转换器执行此操作,如下所示:
class ChartDataRecordCollectionConverter : JsonConverter
{
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param><param name="value">The value.</param><param name="serializer">The calling serializer.</param>
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();
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param><param name="objectType">Type of the object.</param><param name="existingValue">The existing value of object being read.</param><param name="serializer">The calling serializer.</param>
/// <returns>
/// The object value.
/// </returns>
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<long>();
//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<int>()
});
}
}
return result;
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof (ChartDataRecordCollection);
}
}
您可以使用自定义转换器执行此操作,如下所示:
class ChartDataRecordCollectionConverter : JsonConverter
{
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param><param name="value">The value.</param><param name="serializer">The calling serializer.</param>
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();
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param><param name="objectType">Type of the object.</param><param name="existingValue">The existing value of object being read.</param><param name="serializer">The calling serializer.</param>
/// <returns>
/// The object value.
/// </returns>
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<long>();
//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<int>()
});
}
}
return result;
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof (ChartDataRecordCollection);
}
}
我刚刚测试了你的解决方案。不幸的是,它与我在帖子中列出的输出有很大不同。我刚刚测试了你的解决方案。不幸的是,它与我在帖子中列出的输出有很大不同。你做得很好!非常感谢你,你成功了!非常感谢你。
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<ChartDataRecord>
{
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<ChartDataRecordCollection>(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