C# 使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19080326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:01:41  来源:igfitidea点击:

Deserialize to IEnumerable class using Newtonsoft Json.Net

c#.netxamarin.iosjson.netienumerable

提问by redent84

I have a project that is currently using Json.Net for Json deserialization classes like these:

我有一个项目,目前正在使用 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; }
}

So far it works fine.

到目前为止它工作正常。

To make iteration simpler at one point I made Fooclass implement IEnumerable<Bar>like this:

为了让迭代更简单,我让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; }
}

But then it fails deserializing the object. The error is confusing, as it said that it cannot deserialize FooGuidfield, but removing the IEnumerableinterface works again.

但是随后它无法反序列化对象。该错误令人困惑,因为它说它不能反序列化FooGuid字段,但删除IEnumerable接口再次起作用。

The problem is the same in both MonoTouch and MonoDroid environments in simulator or device.

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

Any clue about how to make it work?

有关如何使其工作的任何线索?



Added code to reproduce this issue:

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

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; }
}

Sample project: https://www.dropbox.com/s/27i58aiz71dylkw/IEnumerableJson.zip

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

采纳答案by Brian Rogers

From the Json.Net documentation:

Json.Net 文档

IEnumerable, Lists and Arrays

.NET lists (types that inherit from IEnumerable) and .NET arrays are converted to JSON arrays. Because JSON arrays only support a range of values and not properties, any additional properties and fields declared on .NET collections are not serialized. In situations where a JSON array is not wanted the JsonObjectAttribute can be placed on a .NET type that implements IEnumerable to force the type to be serialized as a JSON object instead.

IEnumerable、列表和数组

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

In other words, since your class implements IEnumerable<T>, Json.Net thinks it is a list. To get around this, simply decorate your class with the [JsonObject]attribute. This will force Json.Net to serialize and deserialize it as a normal class, which is what you want in this case.

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

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