【问题标题】:Json data not converting to ListJson 数据未转换为 List
【发布时间】:2017-03-31 16:32:34
【问题描述】:

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

    }
}

错误的json 这是需要在控制台应用程序中格式化的错误 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
                }
            ]
        }
    }
}

【问题讨论】:

  • 请检查第一个发布的JSON数据,它包含错误。
  • 你的坏 json 有什么不好?
  • @victor- 如果您查看第一个,我有结构和列表-我会看到错误数据中缺少的那些
  • 你有序列化它的代码吗?
  • 看起来这两个 JSON 字符串是使用不同的序列化器序列化的;最简单的事情是找出要使用的正确序列化程序是什么,然后使用理解它的序列化程序反序列化“坏”JSON,并使用“好”序列化程序重新序列化它。第一个 JSON 看起来很不标准,所以如果它是自定义代码,那么您需要复制或重用该代码。

标签: c# json serialization


【解决方案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 值正在转换,但我无法反序列化输出 json,当我更改纬度和经度值 @dbc
  • @kishore - 那么你可能想问第二个问题,或者提供一个 minimal reproducible example 来证明你的新问题。因为您的问题是关于将一​​种 JSON 格式转换为另一种格式,并且根本不涉及反序列化。
  • 链接到我的新问题@dbc stackoverflow.com/questions/43171814/…
  • 我还有一个,我可以把我们的类型、结构、列表作为一个路径,然后把它留给其他路径 byt $type ,$values 无论如何都应该转换
【解决方案2】:

使用Json.NET 序列化和反序列化您的 JSON

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 2014-09-09
    • 2019-05-08
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多