Selaa lähdekoodia

create json-parser function for react-flow

AykutSarac 3 vuotta sitten
vanhempi
commit
d4dfb53e78
1 muutettua tiedostoa jossa 131 lisäystä ja 0 poistoa
  1. 131 0
      src/utils/json-editor-parser.js

+ 131 - 0
src/utils/json-editor-parser.js

@@ -0,0 +1,131 @@
+export function transform(source = [], result = [], nodeInfo = {}) {
+  let { id = 0, parent = null, pAggregate = null, edgeItems = [] } = nodeInfo;
+
+  const createEdgeItem = (id, pid) => ({
+    id: `e${id}-${pid}`,
+    source: id.toString(),
+    target: pid.toString(),
+  });
+
+  if (Array.isArray(source)) {
+    result.push(
+      ...source.flatMap((item, idx) =>
+        parser(item, [], {
+          id: (id + idx).toString(),
+          parent,
+          pAggregate,
+          edgeItems,
+        })
+      )
+    );
+  } else {
+    Object.entries(source).forEach(([key, value], idx) => {
+      const dataNode = {};
+
+      if (value && (Array.isArray(value) || typeof value === "object")) {
+        // every object's iterable property is supposed
+        // to be created as an own parent entity.
+
+        result.push(
+          Object.assign(dataNode, {
+            id: (++id).toString(),
+            data: { label: key },
+            position: { x: 0, y: 0 },
+            type: "special",
+          })
+        );
+        if (parent !== null) {
+          edgeItems.push(createEdgeItem(id, parent.id));
+        }
+        parent = dataNode;
+
+        result.push(
+          ...parser(value, [], {
+            id,
+            parent,
+            pAggregate,
+            edgeItems,
+          })
+        );
+      } else {
+        if (idx === 0) {
+          // every object's first property (though not iterable)
+          // is supposed to be created as an own parent entity.
+
+          result.push(
+            Object.assign(dataNode, {
+              id: (++id).toString(),
+              data: { label: { [key]: value } },
+              position: { x: 0, y: 0 },
+              type: "special",
+            })
+          );
+          if (parent !== null) {
+            edgeItems.push(createEdgeItem(id, parent.id));
+          }
+          pAggregate = parent = dataNode;
+        } else {
+          // aggreagat all non interable properties at
+          // most recent, recursion-free parent level.
+
+          pAggregate.data.label[key] = value;
+        }
+      }
+    });
+  }
+  if (parent === null) {
+    // append all additionally collected edge items
+    // in the end of all the recursion.
+
+    result.push(...edgeItems);
+  }
+  return result;
+}
+
+export const parser = (input) => {
+  const extract = (
+    os,
+    nextId = (
+      (id) => () =>
+        String(++id)
+    )(0)
+  ) =>
+    os.map((o) => ({
+      id: nextId(),
+      data: {
+        label: Object.fromEntries(
+          Object.entries(o).filter(([k, v]) => !Array.isArray(v))
+        ),
+      },
+      position: { x: 0, y: 0 },
+      type: "special",
+      children: Object.entries(o)
+        .filter(([k, v]) => Array.isArray(v))
+        .flatMap(([k, v]) => [
+          {
+            id: nextId(),
+            data: { label: k },
+            position: { x: 0, y: 0 },
+            children: extract(v, nextId),
+            type: "special",
+          },
+        ]),
+    }));
+
+  const relationships = (xs) =>
+    xs.flatMap(({ id: target, children = [] }) => [
+      ...children.map(({ id: source }) => ({
+        id: `e${source}-${target}`,
+        source,
+        target,
+      })),
+      ...relationships(children),
+    ]);
+
+  const flatten = (xs) =>
+    xs.flatMap(({ children, ...rest }) => [rest, ...flatten(children)]);
+
+  const res = extract(input);
+
+  return [...flatten(res), ...relationships(res)];
+};