api design – How can I represent a graph for a visual programming language in JSON?

I am in the process of implementing a visual programming language similar to Blender’s node editor or Unreal Engine Blueprints. It will be implemented as a SPA that will communicate with a JSON based REST API.

I am trying to represent a graph similar to this in JSON:

+------+
|Number|
| Value|-----+  +----------+
+------+     |  |Sum       |
             |  |    Result|
             +--|A         |
+------+     +--|B         |
|Number|     |  +----------+
| Value|-----+
+------+

The best way I can think of doing this is by having two separate lists of JSON objects, one to hold a list of “node definitions” and another representing the graph that will reference the list of node definitions.

Here is the above graph represented in JSON using this approach.

Node definitions:

[
    {
        "name": "num",
        "title": "Number",
        "inputs": [],
        "outputs": [
            {
                "name": "val",
                "label": "Value"
            }
        ]
    },
    {
        "name": "sum",
        "title": "Sum",
        "inputs": [
            {
                "name": "a",
                "label": "A"
            },
            {
                "name": "b",
                "label": "B"
            }
        ],
        "outputs": [
            {
                "name": "res",
                "label": "Result"
            }
        ]
    }
]

Node graph:

{
    "nodes": [
        {
            "id": 0,
            "instanceName": "sum",
            "posX": 200,
            "posY": 85,
        },
        {
            "id": 1,
            "instanceName": "number",
            "posX": 10,
            "posY": 10,
        },
        {
            "id": 2,
            "instanceName": "number",
            "posX": 10,
            "posY": 200,
        }
    ]
    "edges": [
        {
            "source": {
                "nodeId": 1,
                "ioName": "value"
            },
            "target": {
                "nodeId": 0,
                "ioName": "a"
            }
        },
        {
            "source": {
                "nodeId": 2,
                "ioName": "value"
            },
            "target": {
                "nodeId": 0,
                "ioName": "b"
            }
        }
    ]
}

Here are a few potential issues I can see with this approach:

  • The list of node definitions could grow quite large. This could slow things down when trying to load a graph from the server as you would have to load both the list of node definitions and the node graph itself.
  • Maybe it would be a better idea to replace the string names for the node definitions and IO definitions with integer identifiers.
  • It might make more sense if the list of nodes in the node graph were an object with key-value pairs where the ID is the key, instead of an array.

Is this a good approach? Is there a better way to do this?