我有一个没有正确序列化的json数据。 我附上了预期的和坏的。
我需要处理坏的json,以正确的格式
预期
"channels": {
"heart-rate": {
"events": {
"type": "Project.Model.ChannelEvents.HeartRateChannelEvent, Project, Version=1.2.7.0, Culture=neutral, PublicKeyToken=null",
"structure": [
"beatsPerMinute",
"offset"
],
"list": [
[
40,
0
]
]
}
},
"location": {
"events": {
"type": "Project.Model.ChannelEvents.LocationChannelEvent, Project, Version=1.2.7.0, Culture=neutral, PublicKeyToken=null",
"structure": [
"latitude",
"longitude",
"offset"
],
"list": [
[
0.0,
0.0,
0
]
]
}
}
}
badjson 这是需要在控制台应用程序中格式化的错误json数据
"channels": {
"heart-rate": {
"events": {
"$type": "System.Collections.Generic.List`1[[Project.Model.Activity+Channel+Event, Project]], mscorlib",
"$values": [{
"$type": "Project.Model.ChannelEvents.HeartRateChannelEvent, Project",
"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
}
]
}
}
}
答案 0 :(得分:1)
首先,输入和输出JSON在语法上都是无效的:它们缺少外括号{
和}
。对于本回答的其余部分,我将假设这是问题中的拼写错误。
假设您尚未执行此操作,则可以按json.net所示安装here,然后使用LINQ to JSON加载和修改您的JSON。使用这种方法可以避免定义与您的JSON完全匹配的c#类型。
您输入的JSON有两个问题:
令牌"channels.heart-rate.events"
和"channels.location.events"
是已包含Json.NET type information的对象数组。 (从"$type"
属性的存在可以清楚地看出,JSON最初是使用Json.NET生成的)
您想要的是将这些数组重新格式化为包含项类型,项属性名称数组和项属性值数组数组的单个对象。
使用TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
格式化了类型信息。您想要添加汇编信息,转换为FormatterAssemblyStyle.Full
格式。
使用LINQ-to-JSON可以纠正这两个问题。假设您有两个流,Stream inputStream
和Stream outputStream
对应于要修复的JSON的流和用于存储固定JSON的流。然后,介绍以下实用程序方法:
public static class JsonExtensions
{
const string JsonTypeName = @"$type";
const string JsonValuesName = @"$values";
public static void ReformatCollections(Stream inputStream, Stream outputStream, IEnumerable<string> paths, Func<string, string> typeNameMapper, Formatting formatting)
{
var root = JToken.Load(new JsonTextReader(new StreamReader(inputStream)) { DateParseHandling = DateParseHandling.None });
root = ReformatCollections(root, paths, typeNameMapper);
var writer = new StreamWriter(outputStream);
var jsonWriter = new JsonTextWriter(writer) { Formatting = formatting };
root.WriteTo(jsonWriter);
jsonWriter.Flush();
writer.Flush();
}
public static JToken ReformatCollections(JToken root, IEnumerable<string> paths, Func<string, string> typeNameMapper)
{
foreach (var path in paths)
{
var token = root.SelectToken(path);
var newToken = token.ReformatCollection(typeNameMapper);
if (root == token)
root = newToken;
}
return root;
}
public static JToken ReformatCollection(this JToken value, Func<string, string> typeNameMapper)
{
if (value == null || value.Type == JTokenType.Null)
return value;
var array = value as JArray;
if (array == null)
array = value[JsonValuesName] as JArray;
if (array == null)
return value;
// Extract the item $type and ordered set of properties.
string type = null;
var properties = new Dictionary<string, int>();
foreach (var item in array)
{
if (item.Type == JTokenType.Null)
continue;
var obj = item as JObject;
if (obj == null)
throw new JsonSerializationException(string.Format("Item \"{0}\" was not a JObject", obj.ToString(Formatting.None)));
var objType = (string)obj[JsonTypeName];
if (objType != null && type == null)
type = objType;
else if (objType != null && type != null)
{
if (type != objType)
throw new JsonSerializationException("Too many item types.");
}
foreach (var property in obj.Properties().Where(p => p.Name != JsonTypeName))
{
if (!properties.ContainsKey(property.Name))
properties.Add(property.Name, properties.Count);
}
}
var propertyList = properties.OrderBy(p => p.Value).Select(p => p.Key).ToArray();
var newValue = new JObject();
if (type != null)
newValue["type"] = JToken.FromObject(typeNameMapper(type));
newValue["structure"] = JToken.FromObject(propertyList);
newValue["list"] = JToken.FromObject(array
.Select(o => (o.Type == JTokenType.Null ? o : propertyList.Where(p => o[p] != null).Select(p => o[p]))));
if (value.Parent != null)
value.Replace(newValue);
return newValue;
}
}
然后,在控制台方法的顶层,您可以按如下方式修复JSON:
Func<string, string> typeNameMapper = (t) =>
{
if (!t.EndsWith(", Version=1.2.7.0, Culture=neutral, PublicKeyToken=null"))
t = t + ", Version=1.2.7.0, Culture=neutral, PublicKeyToken=null";
return t;
};
var paths = new[]
{
"channels.heart-rate.events",
"channels.location.events"
};
JsonExtensions.ReformatCollections(inputStream, outputStream, paths, typeNameMapper, Formatting.Indented);
示例fiddle。
答案 1 :(得分:0)
使用Json.NET序列化和反序列化您的JSON