{"id":838,"date":"2014-12-15T00:00:00","date_gmt":"2014-12-15T00:00:00","guid":{"rendered":"https:\/\/structr.com\/continuous-delivery\/"},"modified":"2025-01-23T11:15:29","modified_gmt":"2025-01-23T11:15:29","slug":"create-graph-structures-from-deeply-nested-json-documents","status":"publish","type":"post","link":"https:\/\/structr.com\/en\/blog\/create-graph-structures-from-deeply-nested-json-documents\/","title":{"rendered":"Create Graph Structures from deeply nested JSON Documents"},"content":{"rendered":"<div class=\"wpb-content-wrapper\"><p>[vc_row][vc_column][vc_column_text]Recently, we did some tests with the current Structr version to see how well Structr can handle deeply nested JSON documents to create graph structures in Neo4j. We found out that it worked quite well up to the second level of object nesting, and only if new objects referenced existing objects either by their UUID or by a scalar value, if the corresponding mapping was defined in the schema.<\/p>\n<p>When it comes to attributes of nested objects being referenced by more complex values, like collections or nested objects themselves, it became difficult in the sense that you had to define a rather complex object mapping in the schema, using things like Notion attributions (using <code>PropertySetNotion<\/code> internally).<\/p>\n<h3 id=\"whats-new\">What&#8217;s new?<\/h3>\n<p>Over the past days, Christian added some improvements to mitigate these issues, making it much easier to create nodes and relationships in Neo4j based on the schema rules in Structr.<\/p>\n<h3 id=\"example\">Example<\/h3>\n<p>To demonstrate the new capabilities, we&#8217;ve created the following example.<\/p>\n<h4 id=\"schema\">Schema<\/h4>\n<p>[\/vc_column_text][vc_single_image image=&#8221;964&#8243; img_size=&#8221;large&#8221;][vc_column_text]The schema rules in Cypher notation:<\/p>\n<pre><code>(:Project)-[:TASK]-&gt;(:Task)<\/code><\/pre>\n<pre><code>(:Task)-[:SUBTASK]-&gt;(:Task)<\/code><\/pre>\n<pre><code>(:Task)&lt;-[WORKS_ON]-(:Worker)<\/code><\/pre>\n<pre><code>(:Worker)-&gt;[:WORKS_AT]-&gt;(:Company)<\/code><\/pre>\n<p>The cardinalities are:<\/p>\n<ul>\n<li>Project 1 -&gt; * Task<\/li>\n<li>Task 1 -&gt; * Task<\/li>\n<li>Worker 1 -&gt; * Task<\/li>\n<li>Worker * -&gt; 1 Company<\/li>\n<\/ul>\n<p>To make the example work, it is important to overwrite the auto-naming and name the attributes exactly as in the example: <code>tasks, parentTask, subtasks, company, worker, workers<\/code> etc..<\/p>\n<p>Make sure the <code>name<\/code> attribute is unique for each type.<\/p>\n<h4 id=\"auto-creation-rules\">Auto-creation Rules<\/h4>\n<p>Instead of using a <code>PropertyNotion<\/code> with <code>autocreate<\/code> flag, you only have to define the following auto-creation rules (ALWAYS) in the Schema Editor:<\/p>\n<ul>\n<li>Project -&gt; Task<\/li>\n<li>Task -&gt; Task<\/li>\n<li>Worker -&gt; Task<\/li>\n<li>Worker -&gt; Company<\/li>\n<\/ul>\n<h4 id=\"json-document\">JSON Document<\/h4>\n<p>The following example JSON document contains all information about the objects to be created. Note that some sub-objects occur multiple times in the document, and if there&#8217;s a unique attribute defined for their type (like e.g. the <code>name<\/code> attribute for Project, Company and Worker), the object is only created once.<\/p>\n<pre><code>{\r\n   \"name\": \"Project1\",\r\n   \"tasks\": [\r\n       {\r\n           \"name\": \"Task1\",\r\n           \"worker\": {\r\n               \"name\": \"Worker1\",\r\n               \"company\": { \r\n                   \"name\": \"Company1\"\r\n               }\r\n           },\r\n           \"subtasks\": [\r\n               {\r\n                   \"name\": \"Subtask1.1\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker1\",\r\n                       \"company\": { \r\n                           \"name\": \"Company1\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask1.2\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker2\",\r\n                       \"company\": { \r\n                           \"name\": \"Company1\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask1.3\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker2\",\r\n                       \"company\": { \r\n                           \"name\": \"Company1\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask1.4\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker3\",\r\n                       \"company\": { \r\n                           \"name\": \"Company2\"\r\n                       }\r\n                   }\r\n               }\r\n           ]\r\n       },\r\n       {\r\n           \"name\": \"Task2\",\r\n           \"worker\": {\r\n               \"name\": \"Worker2\",\r\n               \"company\": { \r\n                   \"name\": \"Company1\"\r\n               }\r\n           }\r\n       },\r\n       {\r\n           \"name\": \"Task3\",\r\n           \"worker\": {\r\n               \"name\": \"Worker3\",\r\n               \"company\": { \r\n                   \"name\": \"Company2\"\r\n               }\r\n           }\r\n       },\r\n       {\r\n           \"name\": \"Task4\",\r\n           \"worker\": {\r\n               \"name\": \"Worker4\",\r\n               \"company\": { \r\n                   \"name\": \"Company3\"\r\n               }\r\n           },\r\n           \"subtasks\": [\r\n               {\r\n                   \"name\": \"Subtask4.1\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker4\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask4.2\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker4\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask4.3\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker4\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   }\r\n               },\r\n               {\r\n                   \"name\": \"Subtask4.4\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker5\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   }\r\n               }\r\n           ]\r\n       },\r\n       {\r\n           \"name\": \"Task5\",\r\n           \"worker\": {\r\n               \"name\": \"Worker5\",\r\n               \"company\": { \r\n                   \"name\": \"Company3\"\r\n               }\r\n           },\r\n           \"subtasks\": [\r\n               {\r\n                   \"name\": \"Subtask5.1\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker4\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   },\r\n                   \"subtasks\": [\r\n                       {\r\n                           \"name\": \"Subtask5.1.1\",\r\n                           \"worker\": {\r\n                               \"name\": \"Worker4\",\r\n                               \"company\": { \r\n                                   \"name\": \"Company3\"\r\n                               }\r\n                           }\r\n                       },\r\n                       {\r\n                           \"name\": \"Subtask5.1.2\",\r\n                           \"worker\": {\r\n                               \"name\": \"Worker4\",\r\n                               \"company\": { \r\n                                   \"name\": \"Company3\"\r\n                               }\r\n                           }\r\n                       }\r\n                   ]\r\n               },\r\n               {\r\n                   \"name\": \"Subtask5.2\",\r\n                   \"worker\": {\r\n                       \"name\": \"Worker4\",\r\n                       \"company\": { \r\n                           \"name\": \"Company3\"\r\n                       }\r\n                   },\r\n                   \"subtasks\": [\r\n                       {\r\n                           \"name\": \"Subtask5.2.1\",\r\n                           \"worker\": {\r\n                               \"name\": \"Worker4\",\r\n                               \"company\": { \r\n                                   \"name\": \"Company3\"\r\n                               }\r\n                           }\r\n                       },\r\n                       {\r\n                           \"name\": \"Subtask5.2.2\",\r\n                           \"worker\": {\r\n                               \"name\": \"Worker4\",\r\n                               \"company\": { \r\n                                   \"name\": \"Company3\"\r\n                               }\r\n                           }\r\n                       }\r\n                   ]\r\n               }\r\n           ]\r\n       }\r\n   ]\r\n}\r\n<\/code><\/pre>\n<p>Just save this document to a file and POST it to the <code>\/projects<\/code> REST endpoint:<\/p>\n<pre><code>$ curl -i -HX-User:admin -HX-Password:admin \"http:\/\/0.0.0.0:8082\/structr\/rest\/projects\" -XPOST -d @\/tmp\/project.json\r\nHTTP\/1.1 100 Continue\r\n\r\nHTTP\/1.1 201 Created\r\nContent-Type: application\/json; charset=utf-8\r\nSet-Cookie: JSESSIONID=rxjhtzyxetnj1l8dx6vg8aejq;Path=\/\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\nLocation: http:\/\/0.0.0.0:8082\/structr\/rest\/projects\/fafeada746ef432196ee2ccfc7e362fc\r\nVary: Accept-Encoding, User-Agent\r\nContent-Length: 121\r\nServer: Jetty(9.1.4.v20140401)\r\n\r\n{\r\n  \"result_count\": 1,\r\n  \"result\": [\r\n    \"fafeada746ef432196ee2ccfc7e362fc\"\r\n  ],\r\n  \"serialization_time\": \"0.000226953\"\r\n}\r\n\r\n<\/code><\/pre>\n<p>The complete graph was created, without creating any redundancy!<\/p>\n<pre><code>curl -i -HX-User:admin -HX-Password:admin \"http:\/\/0.0.0.0:8082\/structr\/rest\/projects\/fafeada746ef432196ee2ccfc7e362fc\/ui\"\r\nHTTP\/1.1 200 OK\r\nContent-Type: application\/json; charset=utf-8\r\nSet-Cookie: JSESSIONID=el6ri37v61wzeuoni7ilgrl0;Path=\/\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\nVary: Accept-Encoding, User-Agent\r\nContent-Length: 1222\r\nServer: Jetty(9.1.4.v20140401)\r\n\r\n{\r\n   \"query_time\": \"0.001580893\",\r\n   \"result_count\": 1,\r\n   \"result\": {\r\n      \"id\": \"fafeada746ef432196ee2ccfc7e362fc\",\r\n      \"name\": \"Project1\",\r\n      \"owner\": {\r\n         \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"name\": \"admin\"\r\n      },\r\n      \"type\": \"Project\",\r\n      \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n      \"deleted\": false,\r\n      \"hidden\": false,\r\n      \"createdDate\": \"2014-12-15T17:47:13+0100\",\r\n      \"lastModifiedDate\": \"2014-12-15T17:47:13+0100\",\r\n      \"visibleToPublicUsers\": false,\r\n      \"visibleToAuthenticatedUsers\": false,\r\n      \"visibilityStartDate\": null,\r\n      \"visibilityEndDate\": null,\r\n      \"tasks\": [\r\n         {\r\n            \"id\": \"517c1a89e44f479eb0802b9045271b4c\",\r\n            \"name\": \"Task1\"\r\n         },\r\n         {\r\n            \"id\": \"dace6757bad94aa0a137420741406699\",\r\n            \"name\": \"Task2\"\r\n         },\r\n         {\r\n            \"id\": \"097729f47768469ebeaacd00ea8a442e\",\r\n            \"name\": \"Task3\"\r\n         },\r\n         {\r\n            \"id\": \"27bfdc1bb293458eab0d912811f610da\",\r\n            \"name\": \"Task4\"\r\n         },\r\n         {\r\n            \"id\": \"b762fd8f2fe24d149d4a220412c56f49\",\r\n            \"name\": \"Task5\"\r\n         }\r\n      ]\r\n   },\r\n   \"serialization_time\": \"0.000166250\"\r\n}\r\n<\/code><\/pre>\n<pre><code>curl -i -HX-User:admin -HX-Password:admin \"http:\/\/0.0.0.0:8082\/structr\/rest\/companies\/ui\"\r\nHTTP\/1.1 200 OK\r\nContent-Type: application\/json; charset=utf-8\r\nSet-Cookie: JSESSIONID=1mc9hmhm2umrm1h60h1vt56o7c;Path=\/\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\nVary: Accept-Encoding, User-Agent\r\nContent-Length: 2668\r\nServer: Jetty(9.1.4.v20140401)\r\n\r\n{\r\n   \"query_time\": \"0.002427711\",\r\n   \"result_count\": 3,\r\n   \"result\": [\r\n      {\r\n         \"id\": \"bc9de3a97bce409da5234e5976355aa9\",\r\n         \"name\": \"Company1\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Company\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"workers\": [\r\n            {\r\n               \"id\": \"2da31b7175cb44c787ff93fe43c7e317\",\r\n               \"name\": \"Worker1\"\r\n            },\r\n            {\r\n               \"id\": \"d980f56aacea4a0bb2cb8cf7b3a740d5\",\r\n               \"name\": \"Worker2\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"8fac823ef76f436c96cfc9e0c4c21fb5\",\r\n         \"name\": \"Company2\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Company\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"workers\": [\r\n            {\r\n               \"id\": \"a9a23f57b9ce4e33bcc1efbfd2537164\",\r\n               \"name\": \"Worker3\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"eb34f6449d69484f93c69320fe95ea24\",\r\n         \"name\": \"Company3\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Company\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"workers\": [\r\n            {\r\n               \"id\": \"eadcb538f90a41838f0196fd74b82037\",\r\n               \"name\": \"Worker4\"\r\n            },\r\n            {\r\n               \"id\": \"8f8bd3613aa543ecae222da22cdd2e14\",\r\n               \"name\": \"Worker5\"\r\n            }\r\n         ]\r\n      }\r\n   ],\r\n   \"serialization_time\": \"0.000221961\"\r\n}\r\n<\/code><\/pre>\n<pre><code>curl -i -HX-User:admin -HX-Password:admin \"http:\/\/0.0.0.0:8082\/structr\/rest\/workers\/ui\"\r\nHTTP\/1.1 200 OK\r\nContent-Type: application\/json; charset=utf-8\r\nSet-Cookie: JSESSIONID=1b6g61a7uo1t016croq1fz2x41;Path=\/\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\nVary: Accept-Encoding, User-Agent\r\nContent-Length: 6253\r\nServer: Jetty(9.1.4.v20140401)\r\n\r\n{\r\n   \"query_time\": \"0.002056031\",\r\n   \"result_count\": 5,\r\n   \"result\": [\r\n      {\r\n         \"id\": \"2da31b7175cb44c787ff93fe43c7e317\",\r\n         \"name\": \"Worker1\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Worker\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"company\": {\r\n            \"id\": \"bc9de3a97bce409da5234e5976355aa9\",\r\n            \"name\": \"Company1\"\r\n         },\r\n         \"tasks\": [\r\n            {\r\n               \"id\": \"9988348105e34b1ab5d365f4e4f7262a\",\r\n               \"name\": \"Subtask1.1\"\r\n            },\r\n            {\r\n               \"id\": \"517c1a89e44f479eb0802b9045271b4c\",\r\n               \"name\": \"Task1\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"d980f56aacea4a0bb2cb8cf7b3a740d5\",\r\n         \"name\": \"Worker2\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Worker\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"company\": {\r\n            \"id\": \"bc9de3a97bce409da5234e5976355aa9\",\r\n            \"name\": \"Company1\"\r\n         },\r\n         \"tasks\": [\r\n            {\r\n               \"id\": \"196189bde51a43afb587563fb47fda91\",\r\n               \"name\": \"Subtask1.2\"\r\n            },\r\n            {\r\n               \"id\": \"bd35947338924daa85b13391083551b1\",\r\n               \"name\": \"Subtask1.3\"\r\n            },\r\n            {\r\n               \"id\": \"dace6757bad94aa0a137420741406699\",\r\n               \"name\": \"Task2\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"a9a23f57b9ce4e33bcc1efbfd2537164\",\r\n         \"name\": \"Worker3\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Worker\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:12+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"company\": {\r\n            \"id\": \"8fac823ef76f436c96cfc9e0c4c21fb5\",\r\n            \"name\": \"Company2\"\r\n         },\r\n         \"tasks\": [\r\n            {\r\n               \"id\": \"779b76705c9b43d598ce971024743b13\",\r\n               \"name\": \"Subtask1.4\"\r\n            },\r\n            {\r\n               \"id\": \"097729f47768469ebeaacd00ea8a442e\",\r\n               \"name\": \"Task3\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"eadcb538f90a41838f0196fd74b82037\",\r\n         \"name\": \"Worker4\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Worker\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"company\": {\r\n            \"id\": \"eb34f6449d69484f93c69320fe95ea24\",\r\n            \"name\": \"Company3\"\r\n         },\r\n         \"tasks\": [\r\n            {\r\n               \"id\": \"8b2dbfcc93b94e428052ff1276991e34\",\r\n               \"name\": \"Subtask4.1\"\r\n            },\r\n            {\r\n               \"id\": \"f4b99c128cc24c518e6f9af5c3affea4\",\r\n               \"name\": \"Subtask4.2\"\r\n            },\r\n            {\r\n               \"id\": \"e6156b8b566e45349e671229ff70f9ea\",\r\n               \"name\": \"Subtask4.3\"\r\n            },\r\n            {\r\n               \"id\": \"27bfdc1bb293458eab0d912811f610da\",\r\n               \"name\": \"Task4\"\r\n            },\r\n            {\r\n               \"id\": \"5e45f0d22ee944ec84bc31aa75b40dda\",\r\n               \"name\": \"Subtask5.1.1\"\r\n            },\r\n            {\r\n               \"id\": \"2e21cad09d09423dacec07abcc763c3f\",\r\n               \"name\": \"Subtask5.1.2\"\r\n            },\r\n            {\r\n               \"id\": \"ad2e56c80ea944808b7082cdcab9f659\",\r\n               \"name\": \"Subtask5.1\"\r\n            },\r\n            {\r\n               \"id\": \"6173bc32066b40498147630d92c17990\",\r\n               \"name\": \"Subtask5.2.1\"\r\n            },\r\n            {\r\n               \"id\": \"83889c6a55f043c6bd69dc04614ff76f\",\r\n               \"name\": \"Subtask5.2.2\"\r\n            },\r\n            {\r\n               \"id\": \"e04e9f77fa444c40904b474f27bcdc61\",\r\n               \"name\": \"Subtask5.2\"\r\n            }\r\n         ]\r\n      },\r\n      {\r\n         \"id\": \"8f8bd3613aa543ecae222da22cdd2e14\",\r\n         \"name\": \"Worker5\",\r\n         \"owner\": {\r\n            \"id\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n            \"name\": \"admin\"\r\n         },\r\n         \"type\": \"Worker\",\r\n         \"createdBy\": \"f02e59a47dc9492da3e6cb7fb6b3ac25\",\r\n         \"deleted\": false,\r\n         \"hidden\": false,\r\n         \"createdDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"lastModifiedDate\": \"2014-12-15T17:47:13+0100\",\r\n         \"visibleToPublicUsers\": false,\r\n         \"visibleToAuthenticatedUsers\": false,\r\n         \"visibilityStartDate\": null,\r\n         \"visibilityEndDate\": null,\r\n         \"company\": {\r\n            \"id\": \"eb34f6449d69484f93c69320fe95ea24\",\r\n            \"name\": \"Company3\"\r\n         },\r\n         \"tasks\": [\r\n            {\r\n               \"id\": \"7785c5445d2147578bc8831797241e53\",\r\n               \"name\": \"Subtask4.4\"\r\n            },\r\n            {\r\n               \"id\": \"b762fd8f2fe24d149d4a220412c56f49\",\r\n               \"name\": \"Task5\"\r\n            }\r\n         ]\r\n      }\r\n   ],\r\n   \"serialization_time\": \"0.000484448\"\r\n}\r\n<\/code><\/pre>\n<p>Isn&#8217;t that fascinating? \ud83d\ude42<\/p>\n<h3 id=\"how-it-works\">How it works<\/h3>\n<h4 id=\"workflow\">Workflow<\/h4>\n<p>The parser (GSON) creates a nested structure of maps (JsonInput) from the JSON, which are recursively matched against the schema rules, starting from the innermost object. Structr uses a so-called &#8220;DeserializationStrategy&#8221; to find out whether a nested object already exists in the graph (and can therefore be linked directly), or whether it should be created according to the autocreation rules in the schema.<\/p>\n<h4 id=\"recursive-evaluation\">Recursive evaluation<\/h4>\n<p>When parsing the above JSON document, Structr looks for a Project with the name `Project1` and an array of Tasks with the names `Task1` to `Task5`. To look up the first Task with name `Task1`, Structr recursively calls the DeserializationStrategy to obtain the desired Task, and does this again for the Worker and the Workers&#8217; Company. Since the Company entity has no more nested elements, the recursion stops and Structr looks for a Company with the name `Company1` in the database. The company does not exist, so the autocreation settings cause it to be created and returned to the previous recursion level, where it is linked to the newly created Worker with the name `Worker1`.<\/p>\n<p>This process recursively creates new entites, or fetches them from the database if they already exist, mapping the nested JSON document to a graph structure according to the schema rules.<\/p>\n<h3 id=\"structr-as-a-document-database\">Structr as a Document Database<\/h3>\n<p>The described feature will greatly enhance the document database capabilities of Structr, and be part of the upcoming 1.1 release.<\/p>\n<p>You can find the test code for this particular example behind the following link:<\/p>\n<p><a href=\"https:\/\/github.com\/structr\/structr\/blob\/master\/structr-rest\/src\/test\/java\/org\/structr\/rest\/document\/DocumentTest.java\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/structr\/structr\/blob\/master\/structr-rest\/src\/test\/java\/org\/structr\/rest\/document\/DocumentTest.java<\/a><br \/>\n&lt;\/Cutting deployment times by up to 95%;p&gt;[\/vc_column_text][\/vc_column][\/vc_row]<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>[vc_row][vc_column][vc_column_text]Recently, we did some tests with the current Structr version to see how well Structr can handle deeply nested JSON \u2026<\/p>\n","protected":false},"author":2,"featured_media":964,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[29,30,23,27],"tags":[269,272,273,280,185,278,277,254,265,268,275,266,267,279,270,57,264,276,274,271],"class_list":["post-838","post","type-post","status-publish","format-standard","hentry","category-example","category-document-database","category-neo4j","category-rest","tag-auto-creation-rules","tag-company-relationships","tag-deserializationstrategy","tag-document-database","tag-graph-database","tag-gson-parser","tag-json-to-graph-conversion","tag-neo4j-integration","tag-nested-json-documents","tag-object-mapping","tag-project-management","tag-recursive-evaluation","tag-schema-rules","tag-structr-1-1-release","tag-structr-document-database","tag-structr-features","tag-structr-json-parsing","tag-structr-performance","tag-structr-workflow","tag-task-management"],"acf":[],"_links":{"self":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/838","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/comments?post=838"}],"version-history":[{"count":6,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/838\/revisions"}],"predecessor-version":[{"id":2284,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/838\/revisions\/2284"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/media\/964"}],"wp:attachment":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/media?parent=838"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/categories?post=838"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/tags?post=838"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}