使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类 [英] Deserialize to IEnumerable class using Newtonsoft Json.Net

查看:16
本文介绍了使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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 如下:

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

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 接口再次起作用.

But then it fails deserializing the object. The error is confusing, as it said that it cannot deserialize FooGuid field, but removing the IEnumerable interface works again.

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

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

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

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

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

推荐答案

来自 Json.Net 文档:

IEnumerable、列表和数组

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

.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,Json.Net 认为它是一个列表.要解决此问题,只需使用 [JsonObject] 属性装饰您的类.这将强制 Json.Net 将其序列化和反序列化为普通类,这就是您在本例中想要的.

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.

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

这篇关于使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆