json-editor-parser.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import toast from "react-hot-toast";
  2. const filterChild = ([k, v]) => {
  3. const notNull = v !== null;
  4. const isArray = Array.isArray(v) ? !!v.length : typeof v === "object";
  5. return notNull && isArray;
  6. };
  7. const filterValues = ([k, v]) => {
  8. if (Array.isArray(v) || v instanceof Object) return false;
  9. return true;
  10. };
  11. function generateChildren(object: Object, nextId: () => string) {
  12. return Object.entries(object)
  13. .filter(filterChild)
  14. .flatMap(([k, v]) => [
  15. {
  16. id: nextId(),
  17. text: k,
  18. parent: true,
  19. children: extract(v, nextId),
  20. },
  21. ]);
  22. }
  23. function generateNodeData(object: Object | number) {
  24. const isObject = object instanceof Object;
  25. if (isObject) {
  26. const entries = Object.entries(object).filter(filterValues);
  27. return Object.fromEntries(entries);
  28. }
  29. return object.toString();
  30. }
  31. const extract = (
  32. os: string[] | object[] | null,
  33. nextId = (
  34. (id) => () =>
  35. String(++id)
  36. )(0)
  37. ) => {
  38. if (!os) return [];
  39. return [os].flat().map((o) => ({
  40. id: nextId(),
  41. text: generateNodeData(o),
  42. children: generateChildren(o, nextId),
  43. parent: false,
  44. }));
  45. };
  46. const flatten = (xs: { id: string; children: never[] }[]) =>
  47. xs.flatMap(({ children, ...rest }) => [rest, ...flatten(children)]);
  48. const relationships = (xs: { id: string; children: never[] }[]) => {
  49. return xs.flatMap(({ id: from, children = [] }) => [
  50. ...children.map(({ id: to }) => ({
  51. id: `e${from}-${to}`,
  52. from,
  53. to,
  54. })),
  55. ...relationships(children),
  56. ]);
  57. };
  58. export const parser = (input: string | string[]) => {
  59. try {
  60. if (typeof input !== "object") input = JSON.parse(input);
  61. if (!Array.isArray(input)) input = [input];
  62. const mappedElements = extract(input);
  63. const res = [...flatten(mappedElements), ...relationships(mappedElements)];
  64. return res;
  65. } catch (error) {
  66. console.error(error);
  67. toast.error("An error occured while parsing JSON data!");
  68. return [];
  69. }
  70. };