无法反序列化我的json

编程入门 行业动态 更新时间:2024-10-28 16:20:42
本文介绍了无法反序列化我的json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

这是我的课程

实际上需要转换为良好json数据的初始项. 这是最初的坏人

Initial one which actually needs to be transformed to good json data. This is the initial bad one

{ "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数据,我无法反序列化.即使更改

This is my json data, which i am unable to deserialize. I keep receiving the default values, even when i change

{ "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 ,只要您使用自定义JsonConverer .这是必需的,因为默认情况下,对象集合在JSON数组之间进行序列化,但是在JSON中,对象集合以单个对象的紧凑形式进行序列化,其中对象属性名称已序列化在称为"structure"的字符串数组中只有一次,并且对象本身表示为值数组,内部数组与结构数组成1-1对应.

You can use json to deserialize and re-serialize a List<LocationChannelEvent> in the format shown as long as you use a custom JsonConverer. This is required because, by default, a collection of objects is serialized from and to a JSON array, but in your JSON, a collection of objects is being serialized in a slightly more compact form of a single object where the object property names are serialized only once in an array of strings called "structure", and the objects themselves are represented as an array of array of values, the inner arrays being in 1-1 correspondence to the structure array.

因此,如果您创建以下转换器:

Thus, if you create the following converter:

public class StructuredListConverter<T> : JsonConverter { const string typeName = "type"; const string structureName = "structure"; const string listName = "list"; public override bool CanConvert(Type objectType) { if (!typeof(ICollection<T>).IsAssignableFrom(objectType)) return false; // This converter is only implemented for read/write collections. So no arrays. if (objectType.IsArray) return false; return true; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var collection = existingValue as ICollection<T> ?? (ICollection<T>) serializer.ContractResolver.ResolveContract(objectType).DefaultCreator(); var root = JObject.Load(reader); var structure = root[structureName] == null ? null : root[structureName].ToObject<string []>(); if (structure == null) throw new JsonSerializationException("structure not found."); var listToken = root[listName]; if (listToken == null || listToken.Type == JTokenType.Null) return collection; var list = listToken as JArray; if (list == null) throw new JsonSerializationException("list was not an array."); if (list == null || list.Count == 0) return collection; foreach (var item in list) { if (item == null || item.Type == JTokenType.Null) collection.Add(default(T)); else if (item.Type != JTokenType.Array) throw new JsonSerializationException(string.Format("Item was not an array: {0}", item)); else collection.Add(new JObject(item.Zip(structure, (i, n) => new JProperty(n, i))).ToObject<T>()); } return collection; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var contract = serializer.ContractResolver.ResolveContract(typeof(T)) as JsonObjectContract; if (contract == null) throw new JsonSerializationException(string.Format("Type {0} is not mapped to a JSON object.", typeof(T))); var collection = (ICollection<T>)value; writer.WriteStartObject(); // Write item type writer.WritePropertyName(typeName); serializer.Serialize(writer, typeof(T)); // Write structure (property names) var structure = contract.Properties.Where(p => p.Readable && !p.Ignored).Select(p => p.PropertyName).ToList(); writer.WritePropertyName(structureName); serializer.Serialize(writer, structure); // Write array of array of values var query = collection .Select(i => i == null ? null : contract.Properties.Where(p => p.Readable && !p.Ignored).Select(p => p.ValueProvider.GetValue(i))); writer.WritePropertyName(listName); serializer.Serialize(writer, query); writer.WriteEndObject(); } }

并按如下所示定义数据模型:

And define your data model as follows:

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; } } public class Location { [JsonConverter(typeof(StructuredListConverter<LocationChannelEvent>))] public List<LocationChannelEvent> events { get; set; } } public class RootObject { public Location location { get; set; } }

您将能够反序列化并重新序列化所显示的JSON.

You will be able to deserialize and re-serialize the JSON shown.

原型小提琴.

更多推荐

无法反序列化我的json

本文发布于:2023-11-26 19:42:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1634940.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:序列化   json

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!