// 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:`); } });