【问题标题】:How to deserialize custom json in C#如何在 C# 中反序列化自定义 json
【发布时间】:2018-02-23 21:03:33
【问题描述】:

我正在尝试反序列化一个 JSON 文件,其中元素采用以下格式:

{"include\\fooo\\Gell.h": {
    "parents": [
        "include\\rfg\\ExplorableMa.h"
    ],
    "children": [
        "include\\rfg\\IEditable.h",
        "include\\rfg\\IExplorable.h",
        "Bar"
    ]
}}

JSON 文件中可能有 1 个或多个元素相互跟随。我尝试使用 System.Runtime.Serialization.Json 命名空间,但这段代码并没有取得多大成功:

[DataContract]
class Vertex
{
    [DataMember] public string Path { get; set; }
}

using (Stream stream = File.OpenRead(@"file.json"))
{
    var serializer = new DataContractJsonSerializer(typeof(Vertex[]));
    Vertex[] verteces = (Vertex[])serializer.ReadObject(stream);
    // the array is not valid at this point
}

在这种特定情况下,上面的代码应该用单个顶点填充数组,其路径等于"include\\fooo\\Gell.h"。 反序列化此类 JSON 文件的正确方法是什么?

【问题讨论】:

  • 你听说过Json.net吗?
  • @dbc 我编辑了json,现在它是有效的。
  • @FrankerZ 不,我没有。我宁愿不使用 3rd 方库。为什么在 .Net 中解析 JSON 就这么难?这样的标准格式。
  • 为什么不使用支持良好的第 3 方库?你为什么要反序列化为顶点数组?为什么要反序列化的对象与 JSON 结构不匹配?我在您的 JSON 中看不到 Path 属性。
  • 使用 Newtonsoft.Json。它是一个 3d 派对,但它是一个 Asp.Net mvc 核心依赖项。值得被认为是可靠的。

标签: c# json


【解决方案1】:

使用 Json.Net,您可以以这种方式(或类似方式)反序列化您的文件:

using System.Collections.Generic;
using System.Windows;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

class Vertex
{
    [JsonExtensionData]
    public IDictionary<string, JToken> _additionalData;
}

var content = File.ReadAllText(@"file.json");
var d = JsonConvert.DeserializeObject<Vertex>(content);

看看这些例子:http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data

【讨论】:

    【解决方案2】:

    首先,请注意您的根 JSON 容器是一个对象,而不是一个数组。 JSON standard 指定以下类型的容器:

    • 值的有序集合的数组。数组以[(左括号)开头,以](右括号)结尾。值由,(逗号)分隔。

      大多数 JSON 序列化程序将 .Net 枚举映射到 JSON 数组。

    • 对象是一组无序的名称/值对。对象以{(左大括号)开头,以}(右大括号)结尾。

      大多数 JSON 序列化程序将字典和不可枚举的非原始类型映射到 JSON 对象。

    因此,您将需要反序列化为另一种类型,该类型映射到具有自定义变量属性名称的对象,该对象具有固定模式的值。在这种情况下,大多数序列化程序都支持Dictionary&lt;string, TValue&gt;

    首先定义如下类型:

    public class VertexData
    {
        public List<string> parents { get; set; }
        public List<string> children { get; set; }
    }
    

    然后,使用,您可以按如下方式反序列化为Dictionary&lt;string, VertexData&gt;只要您使用.Net 4.5 或更高版本,如this answer 中所述:

    var serializer = new DataContractJsonSerializer(typeof(Dictionary<string, VertexData>)) { UseSimpleDictionaryFormat = true };
    var vertices = (Dictionary<string, VertexData>)serializer.ReadObject(stream);
    var paths = vertices.Keys.ToList();
    

    如果您更愿意使用,您可以将deserialize 改成相同的Dictionary&lt;string, VertexData&gt;,如下所示:

    using (var reader = new StreamReader(stream))
    using (var jsonReader = new JsonTextReader(reader))
    {
        var vertices = JsonSerializer.CreateDefault().Deserialize<Dictionary<string, VertexData>>(jsonReader);
        var paths = vertices.Keys.ToList();
    }
    

    最后是:

    using (var reader = new StreamReader(stream))
    {
        var jsonString = reader.ReadToEnd();
    
        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        var vertices = serializer.Deserialize<Dictionary<string, VertexData>>(jsonString);
        var paths = vertices.Keys.ToList();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-04
      • 1970-01-01
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多