【问题标题】:Deserialize to IEnumerable class using Newtonsoft Json.Net使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类
【发布时间】:2021-11-10 23:17:19
【问题描述】:

我有一个项目目前正在使用 Json.Net 进行 Json 反序列化类,如下所示:

public class Foo {
    public Guid FooGuid { get; set; }
    public string Name { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar {
    public Guid BarGuid { get; set; }
    public string Description { get; set; }
}

到目前为止一切正常。

为了让迭代更简单,我让Foo 类实现IEnumerable&lt;Bar&gt;,如下所示:

public class Foo : IEnumerable<Bar> {
    public Guid FooGuid { get; set; }
    public string Name { get; set; }
    public List<Bar> Bars { get; set; }

    public IEnumerator<Bar> GetEnumerator()
    {
        return Bars.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class Bar {
    public Guid BarGuid { get; set; }
    public string Description { get; set; }
}

但是它反序列化对象失败。该错误令人困惑,因为它表示它无法反序列化 FooGuid 字段,但删除 IEnumerable 接口再次起作用。

模拟器或设备中的 MonoTouch 和 MonoDroid 环境中的问题是相同的。

关于如何使它工作的任何线索?


添加了重现此问题的代码:

public static class Tests {
    public static void SerializeAndDeserializeFoo() {
        // Serialize and deserialize Foo class
        var element = new Foo
        {
            FooGuid = Guid.NewGuid(),
            Name = "Foo name",
            Bars = new List<Bar> {
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" }
            }
        };

        var serializedObject = JsonConvert.SerializeObject(element);
        Console.WriteLine("Serialized Foo element: {0}", serializedObject);

        // Exception if Foo implements IEnumerable
        var deserializedObject = JsonConvert.DeserializeObject<Foo>(serializedObject);
        Console.WriteLine("Foo deserialization worked!");
    }

    public static void SerializeAndDeserializeEnumerableFoo() {
        // Serialize and deserialize Foo class
        var element = new EnumerableFoo
        {
            FooGuid = Guid.NewGuid(),
            Name = "Foo name",
            Bars = new List<Bar> {
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
                new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" }
            }
        };

        var serializedObject = JsonConvert.SerializeObject(element);
        Console.WriteLine("Serialized EnumerableFoo element: {0}", serializedObject);

        try {
            // Exception if Foo implements IEnumerable
            var deserializedObject = JsonConvert.DeserializeObject<EnumerableFoo>(serializedObject);
            Console.WriteLine("EnumerableFoo deserialization worked!");
        }
        catch (Exception e){
            Console.WriteLine("EnumerableFoo deserialization failed!");
            throw;
        }
    }
}

public class EnumerableFoo : IEnumerable<Bar> {
    public Guid FooGuid { get; set; }
    public string Name { get; set; }
    public List<Bar> Bars { get; set; }

    public IEnumerator<Bar> GetEnumerator()
    {
        return Bars.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class Foo {
    public Guid FooGuid { get; set; }
    public string Name { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar {
    public Guid BarGuid { get; set; }
    public string Description { get; set; }
}

示例项目:https://www.dropbox.com/s/27i58aiz71dylkw/IEnumerableJson.zip

【问题讨论】:

  • 发布一个自包含的可编译代码怎么样?因为我无法复制它。
  • @L.B 添加了示例代码和示例项目。
  • 你不需要实现IEnumerable&lt;Bar&gt;。只要把这个方法public IEnumerator GetEnumerator() { return Bars.GetEnumerator(); } 放到EnumerableFoo (去掉其他GetEnumerators) ,它就可以在foreach
  • JSON.net 文档 (james.newtonking.com/json/help/index.html?topic=html/…) 讨论了序列化 IEnumerables 的限制。

标签: c# .net xamarin.ios json.net ienumerable


【解决方案1】:

来自Json.Net documentation

IEnumerable、列表和数组

.NET 列表(继承自 IEnumerable 的类型)和 .NET 数组转换为 JSON 数组。因为 JSON 数组只支持一系列值而不支持属性,所以在 .NET 集合上声明的任何其他属性和字段都不会序列化。在不需要 JSON 数组的情况下,可以将 JsonObjectAttribute 放在实现 IEnumerable 的 .NET 类型上,以强制将该类型序列化为 JSON 对象。

换句话说,由于你的类实现了IEnumerable&lt;T&gt;,Json.Net 认为它是一个列表。要解决这个问题,只需使用 [JsonObject] 属性装饰您的类。这将强制 Json.Net 将其作为普通类进行序列化和反序列化,这就是您在这种情况下想要的。

[JsonObject]
public class EnumerableFoo : IEnumerable<Bar>
{
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-10
    • 2015-02-16
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多