【发布时间】:2017-04-02 18:13:36
【问题描述】:
这是我的课
第一个实际上需要转换为好的 json 数据。 这是最初的坏人
{
"channels": {
"heart-rate": {
"events": {
"$type": "System.Collections.Generic.List`1[[Project.Model.Activity+Channel+Event, Project]], mscorlib",
"$values": [{
"$type": "Project.Model.ChannelEvents.HeartRateChannelEvent, LTF.MyPlan.ActivityUtil",
"beatsPerMinute": 40,
"offset": 0
}
]
}
},
"location": {
"events": {
"$type": "System.Collections.Generic.List`1[[Project.Model.Activity+Channel+Event, Project]], mscorlib",
"$values": [{
"$type": "Project.Model.ChannelEvents.LocationChannelEvent, Project",
"latitude": 0.0,
"longitude": 0.0,
"offset": 0
}
]
}
}
}
}
public class LocationChannelEvent : Activity.Channel.Event
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public float? Distance { get; set; }
public float? Altitude { get; set; }
/// <summary>
/// Speed in m/s
/// </summary>
public float? Speed { get; set; }
这是我无法反序列化的 json 数据。我一直收到默认值,即使我改变了
{
"location": {
"events": {
"$type": "System.Collections.Generic.List`1[[Project.Model.Activity+Channel+Event, Project]], mscorlib",
"$values": [{
"$type": "Project.Model.ChannelEvents.LocationChannelEvent, Project",
"latitude": 0.0,
"longitude": 0.0,
"offset": 0
]
}
}
}
我的自定义封面
public class CompactListConverter : JsonConverter
{
public const string TypeKey = "type";
public const string StructureKey = "structure";
public const string ListKey = "list";
/// <summary>
/// Only convert lists of non-enumerable class types.
/// </summary>
/// <param name="objectType"></param>
/// <returns></returns>
public override bool CanConvert(Type objectType)
{
var objectTypeInfo = objectType.GetTypeInfo();
if (objectTypeInfo.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(List<>))
{
var itemTypeInfo = objectTypeInfo.GenericTypeArguments.Single().GetTypeInfo();
if (itemTypeInfo.IsClass && !typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(itemTypeInfo))
{
return true;
}
}
return false;
}
/// <summary>
/// Generates a wrapper object containing type, structure, and the condensed list.
/// </summary>
/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var list = (IList)value;
if (list.Count > 0)
{
var array = new JArray();
var wrapper = GetWrapper(list, serializer);
foreach (var item in list)
{
var obj = JObject.FromObject(item, serializer);
var itemValues = new JArray();
foreach (var prop in obj.Properties())
{
itemValues.Add(prop.Value);
}
array.Add(itemValues);
}
wrapper.Add(ListKey, array);
wrapper.WriteTo(writer);
}
else
{
new JObject().WriteTo(writer);
}
}
private JObject GetWrapper(IList list, JsonSerializer serializer)
{
var wrapper = new JObject {{TypeKey, list[0].GetType().AssemblyQualifiedName}};
var keys = new JArray();
var first = JObject.FromObject(list[0], serializer);
foreach (var prop in first.Properties())
{
keys.Add(new JValue(prop.Name));
}
wrapper.Add(StructureKey, keys);
return wrapper;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var wrapper = JObject.Load(reader);
var itemType = Type.GetType(wrapper.GetValue(TypeKey).ToObject<string>());
var array = wrapper.GetValue(ListKey) as JArray;
var list = existingValue as IList ?? (IList) Activator.CreateInstance(typeof (List<>).MakeGenericType(new[] {itemType}));
if (array != null && array.Count > 0)
{
var keys = wrapper.GetValue(StructureKey) as JArray ?? new JArray();
foreach (var itemValues in array.Children<JArray>())
{
var item = new JObject();
for (var i = 0; i < keys.Count; i++)
{
item.Add(new JProperty(keys[i].ToString(), itemValues[i]));
}
list.Add(item.ToObject(itemType, serializer));
}
}
return list;
}
}
public class ChannelCompactingConverter : CompactListConverter
{
public override bool CanConvert(Type objectType)
{
return base.CanConvert(objectType)
&& typeof(IList<Activity.Channel.Event>).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
}
【问题讨论】:
-
它没有理由起作用。使用例如json.net,如果您查看docs,您会发现如果启用
TypeNameHandling,您的JSON 应该类似于original question 中的badjson。为什么不直接反序列化 badjson 而不进行转换? -
我到底在哪里使用这个。 typenamehandling-我应该创建一个新的反序列化类
-
您是在问如何直接反序列化您上一个问题中的 badjson,而不进行转换?
-
我想将它转换成太好的 json 并反序列化 - 因为我需要将它保存回 db
-
你确定你不是在这里解决XY problem吗?你原来所谓的 badjson 可以很容易地反序列化,为什么要先转换呢?
标签: c# json deserialization