Shumoku

JSON Schema

NetworkGraph JSON format specification

Purpose of JSON Format

Shumoku's JSON format is designed as an intermediate format.

Custom API / NetBox / CMDB / Monitoring Systems

         Generate JSON

         Render with Shumoku

Main use cases:

  • Programmatic generation — Dynamically generate network diagrams from custom scripts or APIs
  • System integration — Integrate data from CMDBs, monitoring systems, and cloud APIs beyond NetBox
  • Data merging — Combine information from multiple sources into a single diagram

For manual writing, YAML format is more concise. JSON is suited for auto-generation and system integration.

Basic Structure

{
  "version": "1.0.0",
  "name": "Network Name",
  "description": "Optional description",
  "nodes": [],
  "links": [],
  "subgraphs": [],
  "settings": {}
}

nodes

Define devices on the network (routers, switches, servers, etc.).

{
  "nodes": [
    {
      "id": "router1",
      "label": "Core Router",
      "type": "router",
      "vendor": "yamaha",
      "model": "rtx3510",
      "parent": "dc1"
    },
    {
      "id": "switch1",
      "label": ["Main Switch", "(Floor 1)"],
      "type": "l2-switch"
    }
  ]
}

Node Fields

FieldTypeRequiredDescription
idstringYesUnique identifier
labelstring | string[]YesDisplay label (array for multi-line)
typestringDevice type
vendorstringVendor name (for icons)
modelstringDevice model name
servicestringService name (AWS, etc.)
resourcestringResource type
iconstringCustom icon — URL or inline SVG (overrides vendor/type icons)
parentstringSubgraph ID to belong to
ranknumber | stringLayer specification (same value for horizontal alignment)
shapestringShape (rect, rounded, circle, etc.)
styleobjectCustom style
metadataobjectArbitrary metadata

Device Type List

typeDescription
routerRouter
l2-switchL2 Switch
l3-switchL3 Switch
firewallFirewall
load-balancerLoad Balancer
serverServer
access-pointAccess Point
cloudCloud
internetInternet
vpnVPN
databaseDatabase
genericGeneric

Define connections between devices.

{
  "links": [
    {
      "from": {
        "node": "router1",
        "port": "ge-0/0/0",
        "plug": { "module": { "standard": "10GBASE-SR" } }
      },
      "to": {
        "node": "switch1",
        "port": "eth1",
        "plug": { "module": { "standard": "10GBASE-SR" } }
      },
      "vlan": [100, 200]
    },
    {
      "from": "server1",
      "to": "switch1",
      "label": "Management"
    }
  ]
}
FieldTypeRequiredDescription
idstringUnique identifier
fromstring | objectYesSource (node ID or {node, port, ip, plug})
tostring | objectYesDestination
labelstring | string[]Link label
vlannumber[]Array of VLAN IDs
typestringLine type (solid, dashed, thick, double)
arrowstringArrow (none, forward, back, both)
redundancystringRedundancy type (ha, vc, vss, vpc, mlag, stack)
cableobjectCable details (medium, category, length_m)
styleobjectCustom style
metadataobjectArbitrary metadata

Endpoint Format

// Simple format
"from": "router1"

// Detailed format
"from": {
  "node": "router1",
  "port": "ge-0/0/0",
  "ip": "10.0.0.1/30",
  "plug": { "module": { "standard": "10GBASE-SR" } }
}

Link speed is carried per endpoint as the Ethernet standard of the module in the endpoint's plug (plug.module.standard). Faster standards render as thicker lines. Example values: 1000BASE-T, 10GBASE-T, 10GBASE-SR, 25GBASE-SR, 40GBASE-SR4, 100GBASE-SR4, 100GBASE-LR4.

In YAML, standard: on the link is a shorthand that the parser copies onto both endpoint modules. JSON is loaded as the runtime NetworkGraph shape directly, so set plug.module.standard on each endpoint.


subgraphs

Define subgraphs to group devices.

{
  "subgraphs": [
    {
      "id": "dc1",
      "label": "Data Center 1",
      "vendor": "aws",
      "service": "vpc"
    },
    {
      "id": "rack1",
      "label": "Rack A",
      "parent": "dc1"
    }
  ]
}

Subgraph Fields

FieldTypeRequiredDescription
idstringYesUnique identifier
labelstringYesDisplay label
parentstringParent subgraph ID (for nesting)
childrenstring[]Array of child subgraph IDs
directionstringLayout direction (TB, BT, LR, RL)
vendorstringVendor name (for icons)
servicestringService name
filestringExternal file reference (hierarchical)
pinsobject[]Boundary connection points
styleobjectCustom style

settings

Define global settings.

{
  "settings": {
    "direction": "TB",
    "theme": "light",
    "nodeSpacing": 50,
    "rankSpacing": 100,
    "legend": {
      "enabled": true,
      "position": "top-right"
    }
  }
}

Settings Fields

FieldTypeDescription
directionstringLayout direction (TB, BT, LR, RL)
themestringTheme (light, dark)
nodeSpacingnumberNode spacing
rankSpacingnumberRank spacing
subgraphPaddingnumberSubgraph inner padding
legendboolean | objectLegend settings
canvasobjectCanvas size settings

Complete Example

{
  "version": "1.0.0",
  "name": "Office Network",
  "nodes": [
    {
      "id": "inet",
      "label": "Internet",
      "type": "internet"
    },
    {
      "id": "fw1",
      "label": "Firewall",
      "type": "firewall",
      "vendor": "juniper",
      "model": "srx300",
      "parent": "perimeter"
    },
    {
      "id": "core-sw",
      "label": "Core Switch",
      "type": "l3-switch",
      "parent": "core"
    },
    {
      "id": "srv1",
      "label": "Web Server",
      "type": "server",
      "parent": "servers"
    }
  ],
  "links": [
    {
      "from": "inet",
      "to": { "node": "fw1", "port": "ge-0/0/0" }
    },
    {
      "from": {
        "node": "fw1",
        "port": "ge-0/0/1",
        "plug": { "module": { "standard": "10GBASE-SR" } }
      },
      "to": {
        "node": "core-sw",
        "port": "ge-0/0/0",
        "plug": { "module": { "standard": "10GBASE-SR" } }
      }
    },
    {
      "from": {
        "node": "core-sw",
        "port": "ge-0/0/1",
        "plug": { "module": { "standard": "1000BASE-T" } }
      },
      "to": {
        "node": "srv1",
        "port": "eth0",
        "plug": { "module": { "standard": "1000BASE-T" } }
      },
      "vlan": [100]
    }
  ],
  "subgraphs": [
    { "id": "perimeter", "label": "Perimeter" },
    { "id": "core", "label": "Core" },
    { "id": "servers", "label": "Server Room" }
  ],
  "settings": {
    "direction": "TB",
    "theme": "light"
  }
}

Merge Example

Example script to merge JSON from multiple data sources:

// merge-data.js
import { readFileSync, writeFileSync } from 'fs'

// JSON exported from NetBox
const netbox = JSON.parse(readFileSync('netbox.json', 'utf-8'))

// Additional data from custom API
const custom = JSON.parse(readFileSync('custom.json', 'utf-8'))

// Merge nodes (with ID duplication check)
const existingIds = new Set(netbox.nodes.map(n => n.id))
for (const node of custom.nodes) {
  if (!existingIds.has(node.id)) {
    netbox.nodes.push(node)
  }
}

// Add links
netbox.links.push(...custom.links)

// Add subgraphs
if (custom.subgraphs) {
  netbox.subgraphs = netbox.subgraphs || []
  netbox.subgraphs.push(...custom.subgraphs)
}

// Output
writeFileSync('merged.json', JSON.stringify(netbox, null, 2))

Run:

node merge-data.js
npx @shumoku/cli render merged.json -o diagram.html

On this page