Json数据未转换为List

时间:2017-03-31 16:32:35

标签: c# json serialization

我有一个没有正确序列化的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
                }
            ]
        }
    }
}

2 个答案:

答案 0 :(得分:1)

首先,输入和输出JSON在语法上都是无效的:它们缺少外括号{}。对于本回答的其余部分,我将假设这是问题中的拼写错误。

假设您尚未执行此操作,则可以按所示安装here,然后使用LINQ to JSON加载和修改您的JSON。使用这种方法可以避免定义与您的JSON完全匹配的c#类型。

您输入的JSON有两个问题:

使用LINQ-to-JSON可以纠正这两个问题。假设您有两个流,Stream inputStreamStream 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