这是我的课
最初的一个实际上需要转换为良好的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以List<LocationChannelEvent>
显示的格式对a进行反序列化和重新序列化,只要您使用custom即可JsonConverer
。这是必需的,因为默认情况下,对象集合在JSON数组之间进行序列化,但是在JSON中,对象集合以单个对象的紧凑形式进行序列化,其中对象属性名称已序列化在称为的字符串数组中仅出现一次"structure"
,并且对象本身表示为值数组,内部数组与结构数组成1-1对应。
因此,如果您创建以下转换器:
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();
}
}
并如下定义数据模型:
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。
原型小提琴。
1) json: 2) 代码: 错误消息为: 我检查了json文件,它是有效的。 我不知道发生了什么事。
问题内容: 我试图序列化和反序列化内部对象的数组列表: HairList对象也是一个可序列化的对象。 此代码执行返回以下错误: 排队 我不知道我在做什么错。你能给个小费吗? 更新: 解决: 仅使用HairBirt的本机数组而不是ArrayList即可工作: 代替 感谢大家的帮助。 问题答案: 不要使用-而是使用二进制数据并对它进行base64编码,以将其转换为字符串而不会丢失信息。 我强烈怀疑这是
问题内容: 作为一个小项目,我一直在尝试做一个小事,它可以读取序列化的lambda(从本地或从FTP)并调用它们的运行函数作为测试的一部分,以测试Windows中的文件关联(即打开某些文件类型)使用特定程序打开它们),但不管如何,无论如何,它似乎从未正确地反序列化。 lambda被这样声明 并使用由ObjectOutputStream包装的[n可选] BufferedOutputStream包装的
问题内容: 在hibernate状态下执行条件查询时,出现以下异常: 可能是什么问题呢? PS:虽然可能不相关,但我的hibernate版本是hibernate-4.0.1 final。 问题答案: 问题在于被引用的实体对实体有另一个引用,并且该关系未由任何-like注释进行注释。
问题内容: 我正在使用Hibernate的两个表,但我不明白为什么对于特定查询我有此问题。我希望有人意识到这个问题。 我有一个桌子用户 和一个桌子区域 日志说: 问题答案: 我建议仅在字段或getter上设置注释。我更喜欢田野,但那只是我的口味。 请参阅Hibernate中有关字段和属性访问的奇怪案例: 因此,要么将注释仅放置在字段上,要么仅放置在getters(properties)上。混合它们
作为一个小项目,我一直在尝试制作一个小东西来读取序列化的lambda(本地或从FTP)并调用它们的run函数,作为测试的一部分,以在Windows中试验文件关联(即打开某些文件类型会用某个程序打开它们)等等,但无论我尝试什么,它似乎都无法正确地反序列化。 lambda是这样宣布的 并使用由ObjectOutputStream包装的[n可选]BufferedOutputStream包装的FileOu