Skip to content

Instantly share code, notes, and snippets.

@brookjordan
Last active July 22, 2021 03:45
Show Gist options
  • Save brookjordan/fee7065f7047d1a98f0b1486d1adffd6 to your computer and use it in GitHub Desktop.
Save brookjordan/fee7065f7047d1a98f0b1486d1adffd6 to your computer and use it in GitHub Desktop.
Interpret the types of a list of objects and log out a yaml swagger file
// TODO: output “required:” array correctly
const payloads = [{
a: 'one',
b: 2,
c: {
face: 'me'
},
d: [1,2]
},{
a: 'one',
b: 2,
c: null,
d: [3,4],
e: false
}]
/**
* This payload will output the following swagger:
*
* Payload:
* type: object
* properties:
* a:
* required: true
* type: string
* example:
* - 'one'
* b:
* required: true
* type: number
* example:
* - 2
* c:
* required: true
* nullable: true
* type: object
* properties:
* face:
* type: string
* example:
* - 'me'
* d:
* required: true
* type: array
* items:
* type: number
* example:
* - 1
* - 2
* - 3
* - 4
* e:
* type: boolean
* example:
* - false
*
**/
const payloadParts = new Map();
const path = [];
function getParts(obj) {
Object.entries(obj).forEach(([key, value]) => {
path.push(isNaN(key) ? key : '[]');
const pathKey = path.join('.');
if (!payloadParts.has(pathKey)) {
payloadParts.set(pathKey, { types: new Set(), nullable: false, count: 0, examples: new Set() });
}
payloadParts.get(pathKey).count += 1;
if (value === null) {
payloadParts.get(pathKey).nullable = true;
} else if (Array.isArray(value)) {
payloadParts.get(pathKey).types.add('array');
getParts(value);
} else if (typeof value === 'object') {
getParts(value);
} else {
payloadParts.get(pathKey).types.add(typeof value);
if (value != null) {
payloadParts.get(pathKey).examples.add(value);
}
}
path.pop();
});
}
payloads.forEach(payload => {
getParts(payload);
});
console.log(`Payload:`);
console.log(` type: object`);
console.log(` properties:`);
[...payloadParts].sort(([a], [b]) => a.replace(/\./g, ' ').localeCompare(b.replace(/\./g, ' '))).forEach(([path, value]) => {
const key = path.split('.').pop();
const types = [...payloadParts.get(path).types];
const required = payloadParts.get(path).count === payloads.length && !/\./.test(path);
let indentLevel = path.match(/\./g)?.length ?? 0;
indentLevel -= (path.match(/\[\]/g)?.length ?? 0) / 2;
const indent = Array(indentLevel * 4).fill(' ').join('');
if (key !== '[]') {
console.log(` ${indent}${key}:`);
}
if (required) {
console.log(` ${indent}required: true`);
}
if (value.nullable) {
console.log(` ${indent}nullable: true`);
}
if (types.length) {
console.log(` ${indent}type: ${(types.join(', '))}`);
} else {
console.log(` ${indent}type: object`);
}
if (value.examples.size > 0) {
console.log(` ${indent}example:\n ${indent}- ${[...value.examples].map(example => (typeof example === 'string') ? `'${example}'` : example).join(`\n ${indent}- `)}`);
}
if (types.length === 0) {
console.log(` ${indent}properties:`);
} else if (types.includes('array')) {
console.log(` ${indent}items:`);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment