处理JSON.net中的引用循环 [英] Handling reference loops in JSON.net

查看:72
本文介绍了处理JSON.net中的引用循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望将项目集合(List<Item>)序列化为JSON.

I wish to serialize a collection (List<Item>) of items to JSON.

这些项目具有Connection的集合,该集合提供有关从一个Item到第二个Item的连接的信息.并且由于连接对象引用了项目,因此使其成为无限循环.

These items have a collection of Connection which gives information about the connection from one Item to a second Item. And since the connection object has a reference to the items it makes it an infinite loop.

我的问题是,当我第二次序列化对象时,是否可以跳过连接集合的序列化.

我已经尝试了诸如从JsonConverter继承并编写自定义WriteJson()方法的操作,但是从那里我不知道是否应该写出数组.

I've tried things like inheriting from JsonConverter and writing a custom WriteJson() method but from there I have no sence whether I should write out the array or not.

我也尝试过使用自定义的ContractResolver,但效果不佳.

I've also tried using a custom ContractResolver but with no good results.


课程

public class Item
{
    private static int _lastID = 0;

    public Item()
    {
        ID = ++_lastID;
        Connections = new List<Connection>();
    }


    public int ID { get; set; }

    public string Name { get; set; }

    public string Prop1 { get; set; }

    public string Prop2 { get; set; }

    public List<Connection> Connections { get; set; }

}



public class Connection
{
    private Connection(ConnectionType type, Item source, Item target)
    {
        if (type == ConnectionType.None)
            throw new ArgumentException();
        if (source == null)
            throw new ArgumentNullException("source");
        if (target == null)
            throw new ArgumentNullException("target");

        Type = type;
        Source = source;
        Target = target;
    }


    public ConnectionType Type { get; set; }

    public Item Source { get; set; }

    public Item Target { get; set; }


    public static void Connect(ConnectionType type, Item source, Item target)
    {
        var conn = new Connection(type, source, target);
        source.Connections.Add(conn);
        target.Connections.Add(conn);
    }
}


想要的结果:

[
    {
        "id": 1,
        "name": "Item #1",
        "prop1": "val1",
        "prop2": "val2",
        "connections": {
            "type": "ConnType",
            "source": {
                "id": 1,
                "name": "Item #1",
                "prop1": "val1",
                "prop2": "val2"
                // no connections array
            },
            "target": {
                "id": 2,
                "name": "Item #2",
                "prop1": "val1",
                "prop2": "val2"
                // no connections array
            }
        }
    },
    {
        "id": 2,
        "name": "Item #2",
        "prop1": "val1",
        "prop2": "val2",
        "connections": {
            "type": "ConnType",
            "source": {
                "id": 1,
                "name": "Item #1",
                "prop1": "val1",
                "prop2": "val2"
                // no connections array
            },
            "target": {
                "id": 2,
                "name": "Item #2",
                "prop1": "val1",
                "prop2": "val2"
                // no connections array
            }
        }
    }
]





C#

var settings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        Formatting = Formatting.Indented
    };
settings.Converters.Add(new StringEnumConverter());
var json = JsonConvert.SerializeObject(collection, settings);

推荐答案

您可以引入一个新类,例如ItemClass,而不是从Item声明SourceTarget的类型.将包含Item类的所有字段,除了Connections属性.

Instead of declaring the type of Source and Target as of Item, you may introduce a new class, say, ItemClass, which'll contain all the fields of class Item, except the Connections property.

public class ItemClass
{
    public int ID { get; set; }

    public string Name { get; set; }

    public string Prop1 { get; set; }

    public string Prop2 { get; set; }
}

public class Connection
{
    // ...

    public ConnectionType Type { get; set; }

    public ItemClass Source { get; set; }

    public ItemClass Target { get; set; }

    // ...
}

现在,您将需要相应地填充新的ItemClass类型实例的开销.

Now you'll have an overhead of populating the new ItemClass type instance accordingly.

这篇关于处理JSON.net中的引用循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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