如何使用Newtonsoft Json.Net将类反序列化为IEnumerable类?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (92)

我有一个项目,目前正在使用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<Bar>如下所示:

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

提问于
用户回答回答于

Json.Net文档

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

换句话说,因为你的类实现了IEnumerable<T>,Json.Net认为它是一个列表。为了解决这个问题,只需用[JsonObject]属性来修饰你的类。这将迫使Json.Net将它作为一个普通的类来序列化和反序列化,这正是你想要的。

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

扫码关注云+社区