Link contouring in JSON.net

I want to serialize assembly ( List<Item>) of elements in JSON.

These elements have a collection Connectionthat gives connection information from one Itemto the second Item. And since the connection object has a reference to the elements, it makes it an infinite loop.

My question is, is there a way for me to skip serializing the connection collection when re-serializing the object.

I tried things like inheriting from JsonConverterand writing a custom method WriteJson(), but from there I have no value whether I should write out an array or not.

I also tried using a custom ContractResolver, but without good results.


Classes

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


Required Result:

[
    {
        "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
            }
        }
    }
]



EDIT:

WITH#

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

Source Target Item , , ItemClass, Item, Connections.

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 .

+1

Global.asax( WebApiConfig )

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+1

, Json (. (, )?).

, , .

I suggest connecting connections to the client using only identifiers, with connections as a separate object.

Add attribute JsonIgnoreto property Connectionsin Item.

[JsonIgnore]
public List<Connection> Connections { get; set; }

And use the class to send to the client, not directly from the list of items.

    class ConnectionContainer
    {
        private readonly List<Item> _items;
        private readonly List<ConnectionInfo> _connections;

        public ConnectionContainer(IEnumerable<Item> items)
        {
            _items = items.ToList();
            Connections = items.SelectMany(i => i.Connections).Distinct().Select(c => new ConnectionInfo
            {
                Type = c.Type,
                SourceId = c.Source.ID,
                TargetId = c.Target.ID
            }).ToList();
        }

        public List<Item> Items
        {
            get { return _items; }
        }

        public List<ConnectionInfo> Connections
        {
            get { return _connections; }
        }
    }

    class ConnectionInfo
    {
        private ConnectionType Type { get; set; }
        private int SourceId { get; set; }
        private int TargetId { get; set; }
    }
0
source

If I'm not mistaken, you only need to save the first link depth containing the collection of connections. If so, try using:

settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.MaxDepth = 1;
0
source

Source: https://habr.com/ru/post/1530950/


All Articles