Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This is a script to take in a {json:api} document (jsonapi.org) and generate a visual graph (http://www.graphviz.org) representation of it
/*
This is a script to take in a {json:api} document (jsonapi.org)
and generate a graphviz (http://www.graphviz.org) representation of it.
Usage:
> node <this_file>
then copy and paste the output to some graphviz parser
e.g. http://www.webgraphviz.com or http://gravizo.com
*/
const sampleJson = {
data: [{
type: 'articles',
id: '1',
attributes: {
title: 'JSON API paints my bikeshed!'
},
links: {
self: 'http://example.com/articles/1'
},
relationships: {
author: {
links: {
self: 'http://example.com/articles/1/relationships/author',
related: 'http://example.com/articles/1/author'
},
data: { type: 'people', id: '9' }
},
comments: {
links: {
self: 'http://example.com/articles/1/relationships/comments',
related: 'http://example.com/articles/1/comments'
},
data: [
{ type: 'comments', id: '5' },
{ type: 'comments', id: '12' }
]
}
}
}],
included: [{
type: 'people',
id: '9',
attributes: {
firstname: 'Dan',
lastname: 'Gebhardt',
twitter: 'dgeb'
},
links: {
self: 'http://example.com/people/9'
}
}, {
type: 'comments',
id: '5',
attributes: {
body: 'First!'
},
relationships: {
author: {
data: { type: 'people', id: '2' }
}
},
links: {
self: 'http://example.com/comments/5'
}
}, {
type: 'comments',
id: '12',
attributes: {
body: 'I like XML better'
},
relationships: {
author: {
data: { type: 'people', id: '9' }
}
},
links: {
self: 'http://example.com/comments/12'
}
}]
};
function ensureArray(obj) {
if (obj instanceof Array) {
return obj;
} else {
return [obj];
}
}
function safeLabel(string) {
return string.toString().replace(/-/g, '_');
}
let header = ["digraph MyFlow {", "node [fontname=\"Courier\"];"];
let relationships = [];
let footer = ["}"]
let entityData = ensureArray(sampleData.data);
let allObjects = entityData.concat(sampleData.included);
allObjects.map((entity) => {
let currentEntityName = safeLabel(`${entity.type}_${entity.id}`);
let label = [`${entity.type} ${entity.id}`];
if (entity.attributes) {
Object.keys(entity.attributes).forEach(function (attributeName) {
label.push(`${attributeName}: ${entity.attributes[attributeName]}`)
});
}
header.push(`${currentEntityName} [label=\"${label.join('\\n')}\" shape=\"box\"]`);
if (entity.relationships) {
Object.keys(entity.relationships).forEach(function (relName) {
let entityRel = entity.relationships[relName].data;
if (entityRel) {
let dataArray = ensureArray(entityRel);
dataArray.map((relRef) => {
relRefName = safeLabel(`${relRef.type}_${relRef.id}`);
relationships.push(`${currentEntityName}->${relRefName} [label=""];`);
});
}
});
}
});
let graphvizParams = header.concat(relationships.concat(footer)).join("\n");
console.log(graphvizParams);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.