When I installed this, it added React 16 to my dependency list. So I decided to rewrite it in JS. No building, no dependencies other than the CSS file in the project:
import "./JsonToTable.css";
const toTitleCase = (str) => {
return str.split(' ')
.map(w => `${w[0]?.toUpperCase() || ''}${w.substring(1)?.toLowerCase() || ''}`)
.join(' ');
}
const JSONObjectType = {
Array: 'Array',
ObjectWithNonNumericKeys: 'ObjectWithNonNumericKeys',
Object: 'Object',
Primitive: 'Primitive'
}
const JSONToTableUtils = {
/**
* Get object type
*/
getObjectType: (obj) => {
if (obj !== null && typeof obj === "object") {
if (Array.isArray(obj)) {
return JSONObjectType.Array;
} else {
if (Object.keys(obj).length) {
return JSONObjectType.ObjectWithNonNumericKeys;
} else {
return JSONObjectType.Object;
}
}
} else {
return JSONObjectType.Primitive;
}
},
checkLabelTypes: (labels) => {
const reduced = labels.reduce(
(accumulator, value) =>
accumulator + (isNaN(Number(value)) ? value : Number(value)),
0
);
return typeof reduced === "number" ? "number" : "string";
},
getUniqueObjectKeys: (anArray) => {
let labels = [];
const objectType = JSONObjectType.Object;
anArray.forEach(item => {
labels = labels.concat(Object.keys(item)).filter((elem, pos, arr) => {
return arr.indexOf(elem) === pos;
});
});
return { labels, type: objectType };
}
}
export const JsonToTable = ({ jsonData }) => {
const renderRowHeader = (label) => {
return (
<div key={`__j2t_rw${label}`}>
<strong>{toTitleCase(label)}</strong>
</div>
);
};
const renderRows = (obj) => {
return Object.keys(obj).map((k, idx) => {
const value = obj[k];
const isValuePrimitive =
JSONToTableUtils.getObjectType(value) === JSONObjectType.Primitive;
// render row when value is primitive otherwise inspect the value and make the key as header
const retval = isValuePrimitive
? renderRow(k, value, idx)
: renderObject(value, k, idx);
return retval;
});
};
const parseArray = (anArray) => {
const phrase = [];
const labels = JSONToTableUtils.getUniqueObjectKeys(
anArray
);
if (JSONToTableUtils.checkLabelTypes(labels.labels) !== "number") {
phrase.push(renderHeader(labels.labels));
phrase.push(renderRowValues(anArray, labels.labels));
} else {
phrase.push(renderValues(anArray));
}
return phrase;
};
const renderObject = (obj, header, idx) => {
const phrase = [];
let tmp;
if (header) {
phrase.push(renderRowHeader(header));
}
const objType = JSONToTableUtils.getObjectType(obj);
switch (objType) {
case JSONObjectType.ObjectWithNonNumericKeys:
tmp = header ? (
<table key={`__j2t_tableObj${idx}`}>
<tbody
key={`__j2t_bObj${idx}`}
>
{renderRows(obj)}
</tbody>
</table>
) : (
renderRows(obj)
);
break;
case JSONObjectType.Array:
tmp = header ? (
<table key={`__j2t_tableArr${idx}`}>
<tbody key={`__j2t_bArr${idx}`}>
{parseArray(obj)}
</tbody>
</table>
) : (
parseArray(obj)
);
break;
}
phrase.push(tmp);
const retval = phrase.map(p => p);
return header ? (
<tr key={`__j2t_trObj${idx}`}>{renderCell({ content: retval, colspan: 2 })}</tr>
) : (
retval
);
};
const getCellValue = (content) => {
const valueDisplay = content === true || content === false ? content.toString() : content;
return valueDisplay;
};
const renderCell = ({
content,
colspan,
isHeader
}) => {
const valueDisplay = isHeader ? <strong>{getCellValue(toTitleCase(content))}</strong> : getCellValue(content);
return <td colSpan={colspan ? colspan : 0} key={`__j2t_trObj${valueDisplay}`}>{valueDisplay}</td>;
};
const renderHeader = (labels) => {
return (
<tr key={`__j2t_trHeader`}>
{labels.map((v) => {
return renderCell({ content: v, isHeader: true });
})}
</tr>
);
};
const renderValues = (values) => {
return (
<tr key={`__j2t_trArrString`}>
{values.map(k => {
return renderCell({ content: k });
})}
</tr>
);
};
const renderRowValues = (anArray, labels) => {
return anArray.map((item, idx) => {
return (
<tr key={`__j2t_Arr${idx.toString()}`}>
{labels.map(k => {
const isValuePrimitive =
JSONToTableUtils.getObjectType(item[k]) === JSONObjectType.Primitive;
return isValuePrimitive
? renderCell({ content: item[k] })
: renderObject(item[k], k, idx);
})}
</tr>
);
});
};
const renderRow = (k, v, idx) => {
return (
<tr key={`__j2t_tr${idx}`}>
<td key={`__j2t_tdk${idx}`}>
<strong>{k}</strong>
</td>
<td key={`__j2t_tdv${idx}`}>{v}</td>
</tr>
);
};
return (
<div className={'json-to-table'}>
<table key={`__j2t_root_table`}>
<tbody key={`__j2t_root_tbody`}>{renderObject(jsonData, undefined, 0)}</tbody>
</table>
</div>
);
}
When I installed this, it added React 16 to my dependency list. So I decided to rewrite it in JS. No building, no dependencies other than the CSS file in the project: