Repository navigation
Json Serialization Updates for Dynamo #7747
Copy link
Copy link
Closed
Labels
Milestone
Description
The purpose of this proposal is to define the json graph format for Dynamo graphs. This graph format splits the graph into two parts. The first part represents the topology of the graph using nodes and connectors. The second part contains objects related to the visualization of the graph. Everything not related to describing compute connectivity, or visualizing the graph, will be considered an application concern and will need to be stored elsewhere. An example of this would be Nodes versus Cameras. Nodes are required in the graph to describe function calls, but Cameras are only used by current Dynamo applications to save vector information related to the user's viewpoint when visualizing the scene in 3D.
Motivations
- One graph definition shared between Dynamo, CoGS/TS, and AVP.
- The ability to add custom converters to serialize to property sets.
- Direct serialization of
NodeModels. No moreSerialize()andDeserialize()methods. We will be able to remove inconsistent xml serialization code. Node authors have used attributes and elements non-discriminantly over the years, resulting in bloated parsing and deserialization code. - Refactoring of Dynamo base classes. Properties related to visualization of the graph should live in the view model or the view.
- Move versioning from Dynamo to the graph. As more systems rely on the shared graph format, it will be necessary to have a version which means something across the entire system. It is possible that this version can also be tied to the design script language, and that bi-directional conversion between DS and the graph is a requirement.
What Has Already Been Done
- The graph schema for CoGS. https://dev-cogs.thunderstorm.autodesk.com/computation-graph/v1/docs#operation/executeGraph
- Attribution of Existing Classes to Support Serialization to Json. https://github.com/DynamoDS/Dynamo/blob/master/src/DynamoCore/Graph/Nodes/NodeModel.cs), although it is not used as Dynamo's file format.
- Command line support for graph conversion to json.
Additional Questions and Considerations
- Does the json graph format become Dynamo's one graph format? If so, we will need to edit the proposal below to consider custom nodes.
- If
Portdescriptions are not stored in the graph, where are they stored? Is it possible to have shared function meta-data across Dynamo, AVP, CoGS, and TS. - One source of truth for port and function descriptions. This would benefit localization.
The Proposed Graph Format
{
"Id": "f170f3ea-ae94-43c1-af0c-e2fa76ebc725",
"Name":"My graph",
"Description":"A compute graph.",
"Nodes":[
{
"Id":"aNode",
"ConcreteType":"Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore",
"NodeType":"FunctionNode",
"FunctionSignature":"Autodesk.DesignScript.Geometry.Point.ByCoordinates@double,double,double",
"VariableInputPorts": true,
"Inputs":[
{
"Id":"aPort",
"UseLevels":false,
"SelectedLevel":2,
"KeepListStructure":false
}
],
"Outputs":[],
"Replication":"auto"
}
],
"Connectors":[
{
"Id": "593c497e-08e3-485a-bf5d-1943d87a9c3b",
"Start": "38727d94-86bd-4db8-b2a3-95baa1ac8a85",
"End": "54c0f71a-524b-4443-9972-1e433a0dceb4"
}
],
"Dependencies":[
"b7d9beae-14a0-485b-b259-27d0861eb165",
"e1764a07-f1f4-4257-a672-9920cd7acc4a"
],
"Bindings":[],
"View":{
"X":0.0,
"Y":1000.0,
"Zoom":0.5,
"NodeViews":[
{
"d65016b6-6845-4423-a831-d20cbf7d37d4":{
"Name":"Point.ByCoordinates",
"X":0.0,
"Y":5.0,
"IsVisible":"true",
"IsUpstreamVisible":true
}
}
],
"Cameras":[],
"Annotations":[
{
"Id": "A group of nodes.",
"Nodes": [
"61aa6da7-0f40-4fbd-b600-05e0daf7e70c",
"6f0d0008-b446-40aa-be41-75fb3b375f39",
"00fdf5cf-f509-40d0-afbb-e83957b19cf3",
"3ea93ee6-7419-4e6a-9748-25737de09ff4"
]
}
]
}
}Proposed Changes
| New JSON Graph Format | Current JSON Graph Format | Updates to Dynamo | Comments |
|---|---|---|---|
| Graph | |||
Uuid |
Uuid |
Id |
The unique identifier of the graph. |
Name |
Name |
The user-defined name of the graph. | |
LastModified |
Remove from serialization. | The date/time representing the last update of the graph. | |
LastModifiedBy |
Remove from serialization. | The unique id of the last user who modified the graph. | |
Description |
Description |
A description of the graph. | |
Nodes |
Nodes |
An array of Node objects. |
|
Connectors |
Connectors |
An array of Connector objects. |
|
Dependencies |
Add a Dependencies field to WorkspaceModel`. |
An array of identifiers of graphs that are used as functions in this graph. | |
Bindings |
Bindings |
Change sessionData to Bindings. |
An array of base-64 encoded key value pairs which relate call sites in the graph to data in an associated data store |
View |
Adjust serialization logic to optionally serialize workspace view data. | An optional object which has properties related to the visualization state of the graph | |
| View | |||
X |
X |
Move to WorkspaceViewModel. |
The x coordinate of the upper left corner of the graph relative to the current viewing frame. |
Y |
Y |
Move to WorkspaceViewModel. |
The Y coordinate of the upper left corner of the graph relative to the current viewing frame. |
Zoom |
Zoom |
Move to WorkspaceViewModel. |
The scale factor between 0.0 and 1.0 of the graph. |
Cameras |
Cameras |
Move to WorkspaceViewModel. |
An array of Camera objects. |
Annotations |
Annotations |
Move to WorkspaceViewModel. |
An array of Annotation objects. |
NodeViews |
Adjust serialization logic to optionally serialize node view data. | A map of objects, keyed by the node id, which contains coordinates of each node. | |
| NodeView | |||
Name |
DisplayName |
Change to Name. |
|
X |
X |
Move to NodeViewModel. |
|
Y |
Y |
Move to NodeViewModel. |
|
IsVisible |
IsVisible |
Move to NodeViewModel. |
|
IsUpstreamVisible |
IsUpstreamVisible |
Move to NodeViewModel |
|
| Port | |||
Id |
Uuid |
The identifier of the port. Id should be unique within the graph. | |
UseLevels |
UseLevels |
A bool which specifies whether the selectedLevel and keepListStructure properties are considered. |
|
Level |
Level |
The level, starting from 0 at the leaf nodes, of nested data which is to be extracted at this port. | |
KeepListStructure |
ShouldKeepListStructure |
Rename to KeepListStructure. |
KeepListStructure is a bool which specifies whether the incoming list topology should be maintained in the final data. |
| Node | |||
Id |
Id |
The identifier of the graph. Id should be unique within the graph. | |
ConcreteType |
ConcreteType |
The location of the function identified by the FunctionSignature property. For .net assemblies used in Dynamo, this will be a fully qualified type name like Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore. |
|
NodeType |
NodeType |
The node type to be used on the server. | |
FunctionSignature |
FunctionSignature |
The full qualified name of a function, including its parameters. Parameters are required to disambiguate overloaded functions. | |
Inputs |
InputPorts |
Rename to Inputs. |
An array of port objects. |
Outputs |
OutputPorts |
Rename to Outputs. |
An array of port objects. |
VariableInputPorts |
VariableInputPorts |
A bool which indicates whether the node has a variable number of input ports. | |
Replication |
Replication |
Used to identify the replication strategy used by this node. | |
| Annotation | |||
Id |
Uuid |
The identifier of that annotation. Id should be unique within the document. |
|
Nodes |
SelectedModels |
Rename to Nodes. |
An array of unique identifiers of nodes which are referenced by this annotation. |
Reactions are currently unavailable
Activity
[-]Json Serialization for Dynamo[/-][+]Json Serialization Updates for Dynamo[/+]ikeough commentedon Apr 7, 2017
@kronz I'd like your feedback on the
viewDatasection idea. This separates the graph description required for compute and that for visualization.gregmarr commentedon Apr 11, 2017
We should use the names from the CoGS schema, so they should have initial caps.
radumg commentedon Apr 11, 2017
Really like this idea - fits in well with all the web-centred work being done on Forge, and with the where we want to take things. I have 2 quick questions :
Bindings
Not sure if I understood the
bindingsone correctly.bindings is an array of base-64 encoded key value pairs which relate call sites in the graph to data in an associated data store. This is currently called callSiteData.Is this data that Dynamo will use as inputs for specific nodes ? If yes, great!
If not, it would be good to add such a property to the JSON : the use case I have in mind is a REST service for running Dynamo graphs where you can POST to it everything it needs to run : a
.dynfile and any associateddataorinput values, returning the result (values, JSON or updated data files). Good precedent is Dynamo Studio's web publishing, although i assume that one uploads everything to a server.YAML / RAML / Swagger
It would be great to publish & develop the API definitions in a common & purpose-made format so people can use them in building integrations and apps that interact with Dynamo.
Any thoughts on this ?
ikeough commentedon Apr 12, 2017
@radumg We are building some services internally which will use this graph format. Those services are built using Swagger, so this graph format is actually represented as a JSON schema in the swagger. I'm not very happy with the client code generated by
swagger-codegencurrently, so for the immediate future, the .net clients (at least) for these services will be written by hand. When those services are available, for external users, they'll still be able to call/ourShinyNewService/swagger.jsonto get the schema and build clients of their own.pboyer commentedon Apr 13, 2017
I do not see why we are storing
lastModifiedorlastModifiedBydata in the file format. This is not, strictly speaking, the responsibility of a graph. On a desktop it would be handled by the file system. On the web, it really depends on the storage system, so it shouldn't be stored here.pboyer commentedon Apr 13, 2017
Appending the word
Dataonto a field of a data serialization format is a tautology. It could be removed with minimal loss in readability.pboyer commentedon Apr 13, 2017
Do all of these have to be a
uuid? I'm guessing this is largely for historical purposes, but correct me if I'm wrong. Not all systems will generate equally good uuid's, some implementations are hacks or one-off jobs, so you may want to conceive the format in such a way that the responsibilities of the author and the system are explicit.ikeough commentedon Apr 14, 2017
@boyerp Agreed on the "viewData". We could just have "graph" and "view".
As for the uuids, we should make it clear that we mean this: https://www.iso.org/standard/53416.html
ikeough commentedon Apr 14, 2017
We should also provide the required date/time format if we decide to keep any fields which store date/time. I know @Marrg just ran into this with Dynamo's date/time node supporting any date/time format. This needs to be consistent.
QilongTang commentedon May 23, 2017
@ikeough Green team discussed the json format today and thinking about the following format. The only difference between this and your proposed format is wrapping everything other than
viewblob into agraphblob. Let us know if you think it's OK. Also tasks are coming :){ "graph":{ "Id": "f170f3ea-ae94-43c1-af0c-e2fa76ebc725", "Name":"My graph", "Description":"A compute graph.", "Nodes":[ { "Id":"aNode", "ConcreteType":"Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", "NodeType":"FunctionNode", "FunctionSignature":"Autodesk.DesignScript.Geometry.Point.ByCoordinates@double,double,double", "VariableInputPorts": true, "Inputs":[ { "Id":"aPort", "UseLevels":false, "SelectedLevel":2, "KeepListStructure":false } ], "Outputs":[], "Replication":"auto" } ], "Connectors":[ { "Id": "593c497e-08e3-485a-bf5d-1943d87a9c3b", "Start": "38727d94-86bd-4db8-b2a3-95baa1ac8a85", "End": "54c0f71a-524b-4443-9972-1e433a0dceb4" } ], "Dependencies":[ "b7d9beae-14a0-485b-b259-27d0861eb165", "e1764a07-f1f4-4257-a672-9920cd7acc4a" ], "Bindings":[] } "View":{ "X":0.0, "Y":1000.0, "Zoom":0.5, "NodeViews":[ { "d65016b6-6845-4423-a831-d20cbf7d37d4":{ "Name":"Point.ByCoordinates", "X":0.0, "Y":5.0, "IsVisible":"true", "IsUpstreamVisible":true } } ], "Cameras":[], "Annotations":[ { "Id": "A group of nodes.", "Nodes": [ "61aa6da7-0f40-4fbd-b600-05e0daf7e70c", "6f0d0008-b446-40aa-be41-75fb3b375f39", "00fdf5cf-f509-40d0-afbb-e83957b19cf3", "3ea93ee6-7419-4e6a-9748-25737de09ff4" ] } ] } }gregmarr commentedon May 23, 2017
Graphis already the name of the object that is represented there. It seems weird to have aGraphobject within aGraphobject. What is the purpose of this proposed extra layer?gregmarr commentedon May 23, 2017
I could maybe see putting
NodesandConnectorsinside aComputeobject, as those are the parts needed by the compute component if you want to explicitly call out "compute" vs "view" data, but theID,Name, andDescriptionaren't actually needed by compute.15 remaining items
gregmarr commentedon Jun 10, 2017
@mjkkirschner Makes sense. Can you also give me descriptions of
IsVisibleandIsUpstreamVisibleforNodeView? ShouldAnnotationhave aNamefield?gregmarr commentedon Jun 10, 2017
One more, did we decide that nodes are still UUIDs, or are they free form IDs?
mjkkirschner commentedon Jun 10, 2017
isVisiblereflects the preview state of geometry (is it showing or not in the background preview)IsUpstreamVisiblereflects if the node outputs its upstream nodes into render packages - this is only useful for watch 3d nodes, and I don't know if it works very well.... I think we could get rid of this from Dynamo in the future.Annotationhas a name, though it has a text field.workspaceModelgregmarr commentedon Jun 10, 2017
IsVisibleto something likeIsGeometryVisible,PreviewGeometryorShowGeometry?upstreamout of the schema for now.mjkkirschner commentedon Jun 10, 2017
@gregmarr @ikeough
isVisiblerename... no strong feelings - but that should be straight forward.gregmarr commentedon Jun 10, 2017
Absolutely. The schema should contain exactly those things that every client needs to display the graph.
Otherwise, every client is going to be inventing their own method of storing it, and no one will be able to display anyone else's graph properly.
QilongTang commentedon Jun 16, 2017
Latest schema:
{ "Uuid": "a3198e60-91b1-4425-aeac-35b22642af2e", "IsCustomNode": false, "Description": null, "Name": "Home", "ElementResolver": { "ResolutionMap": {} }, "Nodes": [ { "ConcreteType": "Dynamo.Graph.Nodes.CodeBlockNodeModel, DynamoCore", "NodeType": "CodeBlockNode", "Code": "x=1;", "Id": "a0d3adf8-eda5-47d2-a5e6-4a9bf15f547d", "Inputs": [], "Outputs": [ { "Id": "e127fbd0-eae5-4d19-be8c-cf0cf434a084", "Name": "", "Description": "x", "Level": 2, "UseLevels": false, "KeepListStructure": false } ], "Replication": "Disabled", "Description": "Allows for DesignScript code to be authored directly" } ], "Connectors": [], "Dependencies": [], "Bindings": [], "View": { "Cameras": { "EyePosition": "-17,24,50", "UpDirection": "0,1,0", "LookDirection": "12,-13,-58", "Name": "Background Preview" }, "NodeViews": [ { "Id": "a0d3adf8-eda5-47d2-a5e6-4a9bf15f547d", "Name": "Code Block", "X": 136.0, "Y": 247.0, "IsVisible": true, "IsUpstreamVisible": true } ], "Notes": [ { "Id": "a0a62424-ab53-4b3d-9952-2d876be4e689", "X": 269.5, "Y": 249.5, "Text": "Awesome Note" } ], "Annotations": [ { "Id": "196decf8-2b17-42bf-a9da-f0434030d808", "Title": "Dummy", "Nodes": [ "a0d3adf8-eda5-47d2-a5e6-4a9bf15f547d" ], "Left": 126.0, "Top": 194.0, "Width": 135.05, "Height": 146.0, "FontSize": 36.0, "InitialTop": 247.0, "InitialHeight": 123.0, "TextblockHeight": 43.0, "Background": "#FFC1D676" } ], "X": 0.0, "Y": 0.0, "Zoom": 1.0 } }mjkkirschner commentedon Jun 16, 2017
@QilongTang when
Notesare serialized they should not have aUUIDright? There is a task for serializing them asAnnotations- correct?ramramps commentedon Jun 16, 2017
That is on top of the backlog. Not sure when we will visit that task.
The notes should live inside View block. Do we have a task for it? @QilongTang can you create one if there is not already?
QilongTang commentedon Jun 16, 2017
@mjkkirschner @ramramps Yes, specified in https://jira.autodesk.com/browse/QNTM-908, can we solve them together?
ramramps commentedon Jun 16, 2017
Moving the notes to view block should be done first. It will help the deserilization. Then we can visit this task and do the serialization / deserialization as specified. Makes sense @QilongTang ?
QilongTang commentedon Jun 16, 2017
https://jira.autodesk.com/browse/QNTM-923 and https://jira.autodesk.com/browse/QNTM-908 for moving
Notesfrom graph block into View->Annotation blockradumg commentedon Jun 18, 2017
Quick question on the schema above : will the
"Nodes": []array also allow specification of an entire graph as an object, for use with graph orchestration when/if this ships ?If there is an intention to enable this workflow later on (we absolutely should in my opinion, really need it in practical applications) , would this require the addition of another property at top-level, or does the
IsCustomNodeproperty cover it ?A graph that would be embedded as a node in another graph would then be something like :
Let me know if it's off-topic or for another thread.
QilongTang commentedon Dec 4, 2019
To those still watching this thread, I am closing this since the team has finished the framework of Json serialization as part of Dynamo 2.0. If you have request or questions about schema, please open new issue or PR.