Doubly Linked List to JSON

孤街浪徒 提交于 2019-12-23 11:59:00

问题


I've a three dimensional structure ... actually a doubly linked list with six nodes i.e. left, right, up, down, in, out. if one node is on the right side of other then that node will be defiantly on the left side of the first one. like

Actually this is a 3D structure, but for understanding purposes, I've given a 2D example. Now I've to convert it in JSON format, to send this data through WCF to a client, but as it contains loops so it couldn't be converted to JSON. I've these questions

  1. Can this type of doubly linked list be converted to JSON?
  2. Is there another way to do that?
  3. Any Other recommended Data Structure? If this is impossible using Doubly Linked List.

I'm using Json.Net to handle JSON.

My class is

public class Node
{
    public Document document = null;

    public Node left = null;
    public Node right = null;
    public Node up = null;
    public Node down = null;
    public Node inside = null;
    public Node outside = null;
}

回答1:


Json.Net can handle reference loops if you set the PreserveReferencesHandling option in the settings.

JsonSerializerSettings settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(rootNode, settings);

This setting will cause the JSON to be written with special $id and $ref properties which allow the JSON to be deserialized back to the original references, assuming you are using Json.Net to deserialize on the client side. With this in place you should be able to use your existing object structure with no problem.

Demo:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        Node center = new Node { Name = "In House" };
        Node north = new Node { Name = "North of House" };
        Node west = new Node { Name = "Front of House" };
        Node east = new Node { Name = "Back of House" };
        Node south = new Node { Name = "South of House" };

        center.East = east;
        east.West = center;

        center.West = west;
        west.East = center;

        east.North = north;
        north.East = east;

        east.South = south;
        south.East = east;

        south.West = west;
        west.South = south;

        west.North = north;
        north.West = west;

        DumpNodes(center);

        Console.WriteLine();

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
        settings.NullValueHandling = NullValueHandling.Ignore;
        settings.Formatting = Formatting.Indented;

        string json = JsonConvert.SerializeObject(center, settings);
        Console.WriteLine(json);

        Node node = JsonConvert.DeserializeObject<Node>(json, settings);

        Console.WriteLine();

        DumpNodes(node);
    }

    private static void DumpNodes(Node startingNode)
    {
        HashSet<Node> seen = new HashSet<Node>();
        List<Node> queue = new List<Node>();
        queue.Add(startingNode);
        while (queue.Count > 0)
        {
            Node node = queue[0];
            queue.RemoveAt(0);
            if (!seen.Contains(node))
            {
                seen.Add(node);
                Console.WriteLine(node.Name);
                Look("north", node.North, queue, seen);
                Look("west", node.West, queue, seen);
                Look("east", node.East, queue, seen);
                Look("south", node.South, queue, seen);
            }
        }
    }

    private static void Look(string dir, Node node, List<Node> queue, HashSet<Node> seen)
    {
        if (node != null)
        {
            Console.WriteLine("   " + dir + ": " + node.Name);
            if (!seen.Contains(node))
            {
                queue.Add(node);
            }
        }
    }
}

public class Node
{
    public string Name { get; set; }
    public Node North { get; set; }
    public Node South { get; set; }
    public Node East { get; set; }
    public Node West { get; set; }
}

Output:

In House
   west: Front of House
   east: Back of House
Front of House
   north: North of House
   east: In House
   south: South of House
Back of House
   north: North of House
   west: In House
   south: South of House
North of House
   west: Front of House
   east: Back of House
South of House
   west: Front of House
   east: Back of House

{
  "$id": "1",
  "Name": "In House",
  "East": {
    "$id": "2",
    "Name": "Back of House",
    "North": {
      "$id": "3",
      "Name": "North of House",
      "East": {
        "$ref": "2"
      },
      "West": {
        "$id": "4",
        "Name": "Front of House",
        "North": {
          "$ref": "3"
        },
        "South": {
          "$id": "5",
          "Name": "South of House",
          "East": {
            "$ref": "2"
          },
          "West": {
            "$ref": "4"
          }
        },
        "East": {
          "$ref": "1"
        }
      }
    },
    "South": {
      "$ref": "5"
    },
    "West": {
      "$ref": "1"
    }
  },
  "West": {
    "$ref": "4"
  }
}

In House
   west: Front of House
   east: Back of House
Front of House
   north: North of House
   east: In House
   south: South of House
Back of House
   north: North of House
   west: In House
   south: South of House
North of House
   west: Front of House
   east: Back of House
South of House
   west: Front of House
   east: Back of House

Working fiddle here: https://dotnetfiddle.net/EojsFA




回答2:


What you have is a network. One representation of this is a list of edges. Yours are all bidirectional it seems so it could look like this:

[
    {source:"Left Node", destination:"Center Node"},
    {source:"Center Node", destination:"Up Node"},
    {source:"Center Node", destination:"Down Node"},
    {source:"Center Node", destination:"Right Node"},
    ...
]

You could spit out Json using a traversal of the network. The specific algorithms depend on the specific network you have. However searching on network should give you all the sample code you need.

Doubly linked list is certainly NOT what you need unless you have an extremely specific network that can be traversed in sequence using each edge once only.

Another possibility is that you are really just dealing with Voxels. That is, all your nodes are just coordinates in a 3d cube. The fact that one voxel is adjacent to another then means there is a connection. So if Left Node is at <1,1,1> and Center Node is at <1,2,1> there is a connection because all the coordinates are the same except for Y which differs by only 1. Storage is simply a list of the existing nodes.

Your question mentions a 3D structure, so there seems to be a Voxel representation if nodes are all at a particular distance. If instead the distances are random then you would need to go the network route.




回答3:


Any 3D array (or array of any dimensions for that matter), is essentially a 1D array. You can even think of all arrays being 1D, because a 2D array can be interpreted (logically) as an array of arrays, 3D is an array of arrays of arrays, and so on.

If your structure is like a cubic shape, then it is just a 3D array. It doesn't matter that it is stored in a link list. So to do that, just grab one corner (say low left out), then go through your structure line by line, plane by plane and store objects into a 1D (or 3D) array. Construct it in the same way at the other end.

Your serialization would look something like this (where (x,y,z) is whatever content you have for each node)

[(0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,1,0), (0,1,1), (0,1,2), (0,1,3), ...]

If your structure has an arbitrary 3D shape, then arbitrary pick any node, then view the rest as a tree structure. Each element can have a maximum of 6 child nodes. So let say you pick the "center node", you'd first describe what child nodes it has, then later describe the child nodes of the child nodes, if they have any. Give each node an unique ID to distinguish them. It is important that you describe a node as a child node before you describe the child node of that node, otherwise you'd not be able to construct it at the other end.

Your structure would look like this:

[{id=0, left=1,right=2,up=3,down=null,in=4,out=5},
{id=1, left=6, right=0, up=7, down=null, in=8, out=9},
...]

You can safely ignore any 2-way info in the link list if you wish, because the second way is redundant.



来源:https://stackoverflow.com/questions/24105749/doubly-linked-list-to-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!