jsonParser.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import { Node, parseTree } from "jsonc-parser";
  2. const calculateSize = (
  3. text: string | [string, string][],
  4. isParent = false,
  5. isFolded: boolean
  6. ) => {
  7. let value = "";
  8. if (typeof text === "string") value = text;
  9. else value = text.map(([k, v]) => `${k}: ${v}`).join("\n");
  10. const lineCount = value.split("\n");
  11. const lineLengths = lineCount.map(line => line.length);
  12. const longestLine = lineLengths.sort((a, b) => b - a)[0];
  13. const getWidth = () => {
  14. if (Array.isArray(text) && !text.length) return 40;
  15. if (!isFolded) return 35 + longestLine * 8 + (isParent ? 60 : 0);
  16. if (isParent) return 170;
  17. return 200;
  18. };
  19. const getHeight = () => {
  20. if (lineCount.length * 17.8 < 30) return 40;
  21. return (lineCount.length + 1) * 18;
  22. };
  23. return {
  24. width: getWidth(),
  25. height: getHeight(),
  26. };
  27. };
  28. export const parser = (jsonStr: string, isFolded = false) => {
  29. try{
  30. let json = parseTree(jsonStr);
  31. console.log(json);
  32. let nodes: NodeData[] = [];
  33. let edges: EdgeData[] = [];
  34. const addNodes = (
  35. text: any,
  36. width: number,
  37. height: number,
  38. parent: boolean,
  39. isEmpty?: boolean
  40. ) => {
  41. let actualId = String(nodes.length + 1);
  42. nodes = [
  43. ...nodes,
  44. {
  45. id: actualId,
  46. text: text,
  47. width: width,
  48. height: height,
  49. data: {
  50. isParent: parent,
  51. childrenCount: parent ? 1 : 0,
  52. isEmpty: isEmpty,
  53. },
  54. },
  55. ];
  56. return actualId;
  57. };
  58. const addEdges = (from: string, to: string) => {
  59. edges = [
  60. ...edges,
  61. {
  62. id: `e${from}-${to}`,
  63. from: from,
  64. to: to,
  65. },
  66. ];
  67. };
  68. let parentName: string = "";
  69. let bracketOpen: string[] = [];
  70. let objectsFromArray: number[] = [];
  71. let notHaveParent: string[] = [];
  72. let brothersNode: [string, string][] = [];
  73. let brothersParentId: string | undefined = "";
  74. let brotherKey: string = "";
  75. let brothersNodeProps: {
  76. id: string;
  77. parentId: string | undefined;
  78. objectsFromArrayId: number | undefined;
  79. }[] = [];
  80. const traverse = (
  81. objectToTraverse: Node,
  82. parentType?: string,
  83. myParentId?: string,
  84. nextType?: string
  85. ) => {
  86. let { type, children, value } = objectToTraverse;
  87. if (!children) {
  88. if (value !== undefined) {
  89. if (
  90. parentType === "property" &&
  91. nextType !== "object" &&
  92. nextType !== "array"
  93. ) {
  94. brothersParentId = myParentId;
  95. if (nextType === undefined) {
  96. // add key and value to brothers node
  97. brothersNode = [...brothersNode, [brotherKey, value]];
  98. } else {
  99. brotherKey = value;
  100. }
  101. } else if (parentType === "array") {
  102. const { width, height } = calculateSize(String(value), false, isFolded);
  103. const nodeFromArrayId = addNodes(String(value), width, height, false);
  104. if (myParentId) {
  105. addEdges(myParentId, nodeFromArrayId);
  106. }
  107. }
  108. if (nextType && parentType !== "array") {
  109. if (nextType === "object" || nextType === "array") {
  110. parentName = value;
  111. }
  112. }
  113. }
  114. } else if (children) {
  115. let parentId: string | undefined;
  116. if (type !== "property" && parentName !== "") {
  117. // add last brothers node and add parent node
  118. if (brothersNode.length > 0) {
  119. // end brothers node
  120. const { width, height } = calculateSize(brothersNode, false, isFolded);
  121. const brothersNodeId = addNodes(brothersNode, width, height, false);
  122. brothersNode = [];
  123. if (brothersParentId) {
  124. addEdges(brothersParentId, brothersNodeId);
  125. } else {
  126. notHaveParent = [...notHaveParent, brothersNodeId];
  127. }
  128. brothersNodeProps = [
  129. ...brothersNodeProps,
  130. {
  131. id: brothersNodeId,
  132. parentId: brothersParentId,
  133. objectsFromArrayId: objectsFromArray[objectsFromArray.length - 1],
  134. },
  135. ];
  136. }
  137. // add parent node
  138. const { width, height } = calculateSize(parentName, true, isFolded);
  139. parentId = addNodes(parentName, width, height, true);
  140. bracketOpen = [...bracketOpen, parentId];
  141. parentName = "";
  142. // add edges from parent node
  143. let brothersProps = brothersNodeProps.filter(
  144. e =>
  145. e.parentId === myParentId &&
  146. e.objectsFromArrayId === objectsFromArray[objectsFromArray.length - 1]
  147. );
  148. if (brothersProps.length > 0) {
  149. addEdges(brothersProps[brothersProps.length - 1].id, parentId);
  150. } else if (myParentId) {
  151. addEdges(myParentId, parentId);
  152. } else {
  153. notHaveParent = [...notHaveParent, parentId];
  154. }
  155. } else if (parentType === "array") {
  156. objectsFromArray = [...objectsFromArray, objectsFromArray.length + 1];
  157. }
  158. children.forEach((branch, index, array) => {
  159. if (array[index + 1]) {
  160. traverse(
  161. branch,
  162. type,
  163. bracketOpen[bracketOpen.length - 1],
  164. array[index + 1].type
  165. );
  166. } else {
  167. traverse(branch, type, bracketOpen[bracketOpen.length - 1]);
  168. }
  169. });
  170. if (type !== "property") {
  171. // when children end
  172. if (parentType !== "array") {
  173. if (bracketOpen.length > 0) {
  174. let newBracketOpen = [...bracketOpen];
  175. newBracketOpen.splice(newBracketOpen.length - 1);
  176. bracketOpen = [...newBracketOpen];
  177. }
  178. } else if (parentType === "array") {
  179. if (objectsFromArray.length > 0) {
  180. let newobjectsFromArray = [...objectsFromArray];
  181. newobjectsFromArray.splice(newobjectsFromArray.length - 1);
  182. objectsFromArray = [...newobjectsFromArray];
  183. }
  184. }
  185. // add brothers node when is the last node
  186. if (brothersNode.length > 0) {
  187. const { width, height } = calculateSize(brothersNode, false, isFolded);
  188. const brothersNodeId = addNodes(brothersNode, width, height, false);
  189. brothersNode = [];
  190. if (brothersParentId) {
  191. addEdges(brothersParentId, brothersNodeId);
  192. } else {
  193. notHaveParent = [...notHaveParent, brothersNodeId];
  194. }
  195. brothersNodeProps = [
  196. ...brothersNodeProps,
  197. {
  198. id: brothersNodeId,
  199. parentId: brothersParentId,
  200. objectsFromArrayId: objectsFromArray[objectsFromArray.length - 1],
  201. },
  202. ];
  203. }
  204. if (parentId) {
  205. let myChildrens = edges.filter(e => e.from === parentId);
  206. let myIndex = nodes.findIndex(e => e.id === parentId);
  207. let ModifyNodes = [...nodes];
  208. if (ModifyNodes[myIndex]) {
  209. ModifyNodes[myIndex].data.childrenCount = myChildrens.length;
  210. nodes = [...ModifyNodes];
  211. }
  212. }
  213. }
  214. }
  215. };
  216. if (json) {
  217. traverse(json);
  218. }
  219. if (notHaveParent.length > 1) {
  220. console.log(notHaveParent);
  221. const text = "";
  222. const { width, height } = calculateSize(text, false, isFolded);
  223. const emptyId = addNodes(text, width, height, false, true);
  224. notHaveParent.forEach(children => {
  225. addEdges(emptyId, children);
  226. });
  227. }
  228. if (nodes.length === 0 && json) {
  229. if (json.type === "array") {
  230. const text = "[]";
  231. const { width, height } = calculateSize(text, false, isFolded);
  232. addNodes(text, width, height, false);
  233. } else {
  234. const text = "{}";
  235. const { width, height } = calculateSize(text, false, isFolded);
  236. addNodes(text, width, height, false);
  237. }
  238. }
  239. return { nodes, edges };
  240. } catch (error) {
  241. console.error(error);
  242. return {
  243. nodes: [],
  244. edges: [],
  245. };
  246. }
  247. };