Version: 1.0
Status: Draft
Last Updated: 2026-01-12
- Introduction
- Document Structure
- Components
- Connections
- Groups
- Data Types
- Component-Specific Formats
- Validation
- Examples
GhJSON is a JSON-based format for representing Grasshopper definitions. It provides a human-readable, portable way to serialize and deserialize Grasshopper documents, enabling:
- Version control: Track changes to Grasshopper definitions in Git
- AI integration: Enable AI tools to read and generate Grasshopper definitions
- Cross-platform sharing: Share definitions without binary format dependencies
- Automation: Programmatically create and modify definitions
- Human-readable: JSON format with meaningful property names
- Compact: Optimized representations (e.g., compact pivot format)
- Complete: Captures all necessary information to reconstruct a definition
- Extensible: Supports custom properties and future enhancements
- Backward-compatible: Legacy formats are supported during deserialization
GhJSON files use the .ghjson extension.
GhJSON files MUST be encoded in UTF-8 without BOM.
A GhJSON document is a JSON object with the following top-level structure:
{
"schema": "1.0",
"metadata": { ... },
"components": [ ... ],
"connections": [ ... ],
"groups": [ ... ]
}| Property | Type | Required | Description |
|---|---|---|---|
schema |
string | No | GhJSON schema version (default: "1.0") |
metadata |
object | No | Document metadata |
components |
array | Yes | List of components |
connections |
array | No | List of connections |
groups |
array | No | List of groups |
The metadata object contains information about the document:
{
"metadata": {
"description": "A parametric tower generator",
"author": "Jane Smith",
"version": "2",
"created": "2026-01-10T14:30:00Z",
"modified": "2026-01-11T09:15:00Z",
"rhinoVersion": "8.24",
"grasshopperVersion": "1.0.0007",
"dependencies": ["Kangaroo2", "LunchBox"],
"componentCount": 45,
"connectionCount": 12,
"groupCount": 3
}
}| Property | Type | Description |
|---|---|---|
description |
string | Description of the definition |
author |
string | Author name |
version |
string | Definition version |
created |
string | ISO 8601 creation timestamp |
modified |
string | ISO 8601 modification timestamp |
rhinoVersion |
string | Target Rhino version |
grasshopperVersion |
string | Target Grasshopper version |
dependencies |
string[] | Required plugin dependencies |
componentCount |
integer | Total component count |
connectionCount |
integer | Total connection count |
groupCount |
integer | Total group count |
Components are the core elements of a GhJSON document. Each component represents a Grasshopper component or parameter on the canvas.
{
"name": "Addition",
"library": "Maths",
"nickName": "Add",
"componentGuid": "a0d62394-a118-422d-abb3-6af115c75b25",
"instanceGuid": "12345678-1234-1234-1234-123456789abc",
"id": 1,
"pivot": "100,200",
"inputSettings": [ ... ],
"outputSettings": [ ... ],
"componentState": { ... }
}| Property | Type | Required | Description |
|---|---|---|---|
name |
string | Conditional | Display name of the component |
library |
string | No | Component library/category |
nickName |
string | No | Custom nickname |
componentGuid |
uuid | No | Component type GUID |
instanceGuid |
uuid | No | Instance GUID |
id |
integer | Conditional | Integer ID for references (required when referenced by connections/groups) |
pivot |
string or object | No | Canvas position (string: "X,Y" or object: { "x": 100, "y": 200 }) |
inputSettings |
array | No | Input parameter settings |
outputSettings |
array | No | Output parameter settings |
componentState |
object | No | UI-specific state |
warnings |
string[] | No | Warning messages |
errors |
string[] | No | Error messages |
remarks |
string[] | No | Remark messages |
The pivot property uses a compact string format:
"pivot": "100.5,200.25"Or an explicit object format:
"pivot": { "x": 100.5, "y": 200.25 }Components MUST have at least one identifier (id or instanceGuid). Library implementations MAY auto-assign sequential id values to components lacking identifiers during document construction.
Components can be identified with any of these combinations:
- By Name + ID:
namewith compact integerid - By Name + Instance GUID:
nameplusinstanceGuid - By Component GUID + ID:
componentGuidplusid - By Component GUID + Instance GUID:
componentGuidplusinstanceGuid
You MAY include both componentGuid and name together. For reliable instantiation, include componentGuid and an id when the component will be referenced by connections or groups.
The id property provides a compact integer reference for use in connections and groups. IDs:
- MUST be positive integers (≥ 1)
- MUST be unique within the document
- SHOULD be sequential (1, 2, 3, ...)
The optional inputSettings and outputSettings arrays configure a component's parameters.
Each item is a Parameter Settings object:
| Property | Type | Required | Description |
|---|---|---|---|
parameterName |
string | Yes | The parameter name |
nickName |
string | No | Custom nickname |
variableName |
string | No | Script parameter variable name |
description |
string | No | Parameter description |
dataMapping |
string | No | Mapping mode: none, flatten, graft |
expression |
string | No | Expression (presence implies an expression exists) |
access |
string | No | Script access: item, list, tree |
typeHint |
string | No | Script type hint (e.g., double, Point3d) |
isPrincipal |
boolean | No | Principal/master input |
isRequired |
boolean | No | Required parameter for variable parameter components |
isReparameterized |
boolean | No | Domain reparameterization |
isReversed |
boolean | No | Reverse modifier |
isSimplified |
boolean | No | Simplify modifier |
isInverted |
boolean | No | Invert modifier (boolean params) |
isUnitized |
boolean | No | Unitize modifier (vector params) |
internalizedData |
object | No | Internalized data tree |
Connections represent the wires between component parameters.
{
"connections": [
{
"from": { "id": 1, "paramIndex": 0 },
"to": { "id": 2, "paramIndex": 0 }
}
]
}| Property | Type | Required | Description |
|---|---|---|---|
from |
endpoint | Yes | Source endpoint (output) |
to |
endpoint | Yes | Target endpoint (input) |
| Property | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Component integer ID |
paramName |
string | Conditional | Parameter name (required if paramIndex is not provided) |
paramIndex |
integer | Conditional | Zero-based parameter index (required if paramName is not provided) |
The paramIndex provides reliable parameter matching when parameter names may vary due to localization or custom nicknames.
Groups organize components visually on the canvas.
{
"groups": [
{
"instanceGuid": "abcd1234-5678-90ab-cdef-1234567890ab",
"id": 1,
"name": "Input Parameters",
"color": "argb:255,200,220,255",
"members": [1, 2, 3]
}
]
}| Property | Type | Required | Description |
|---|---|---|---|
instanceGuid |
uuid | Conditional | Group instance GUID (required if id is not provided; both may be present) |
id |
integer | Conditional | Group integer ID (required if instanceGuid is not provided; both may be present) |
name |
string | No | Group name/nickname |
color |
string | No | ARGB color with prefix (argb:A,R,G,B), each channel 0–255 |
members |
integer[] | Yes | Component IDs in this group |
GhJSON uses prefixed string formats for geometric and special data types.
| Type | Format | Example |
|---|---|---|
| Text | text:value |
"text:Hello World" |
| Number | number:value |
"number:3.14159" |
| Integer | integer:value |
"integer:42" |
| Boolean | boolean:value |
"boolean:true" |
| Type | Format | Example |
|---|---|---|
| Point | pointXYZ:x,y,z |
"pointXYZ:1,2,3" |
| Vector | vectorXYZ:x,y,z |
"vectorXYZ:0,0,1" |
| Line | line2p:x1,y1,z1;x2,y2,z2 |
"line2p:0,0,0;1,0,0" |
| Plane | planeOXY:ox,oy,oz;xx,xy,xz;yx,yy,yz |
"planeOXY:0,0,0;1,0,0;0,1,0" |
| Circle | circleCNRS:cx,cy,cz;nx,ny,nz;r;sx,sy,sz |
"circleCNRS:0,0,0;0,0,1;5;1,0,0" |
| Arc | arc3P:x1,y1,z1;x2,y2,z2;x3,y3,z3 |
"arc3P:0,0,0;1,1,0;2,0,0" |
| Box | boxOXY:ox,oy,oz;xx,xy,xz;yx,yy,yz;x0,x1;y0,y1;z0,z1 |
See spec |
| Rectangle | rectangleCXY:cx,cy,cz;xx,xy,xz;yx,yy,yz;w,h |
See spec |
| Interval | interval:min<max |
"interval:0<10" |
| Bounds | bounds:WxH |
"bounds:150x100" |
| Color | argb:a,r,g,b |
"argb:255,128,64,32" |
Number sliders use a compact value format:
{
"name": "Number Slider",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "5.5<0~10>"
}
}
}
}Format: value<min~max> where:
valueis the current valueminis the minimum valuemaxis the maximum value- Decimal precision is determined by the value with the most decimal places
Additional properties:
rounding: Rounding mode ("Round", "None", "Even", "Odd")
{
"name": "Panel",
"componentState": {
"extensions": {
"gh.panel": {
"text": "Hello World",
"multiline": true,
"wrap": true,
"drawIndices": false,
"drawPaths": true,
"alignment": "Left",
"bounds": ["150x100"]
}
}
}
}{
"name": "Value List",
"componentState": {
"extensions": {
"gh.valuelist": {
"listMode": "DropDown",
"items": [
{ "name": "Option A", "expression": "0", "selected": true },
{ "name": "Option B", "expression": "1" },
{ "name": "Option C", "expression": "2" }
]
}
}
}
}listMode is an implementation-defined string (the schema does not enforce a fixed set of values).
Script components (C#, Python 3, IronPython 2) store their code and configuration in the componentState.extensions object:
{
"name": "C# Script",
"inputSettings": [
{
"parameterName": "x",
"variableName": "x",
"typeHint": "double",
"access": "item"
}
],
"outputSettings": [
{
"parameterName": "A",
"variableName": "A",
"typeHint": "object"
}
],
"componentState": {
"extensions": {
"gh.csharp": {
"code": "A = x * 2;",
"showStandardOutput": true,
"avoidMarshalGuids": true,
"avoidGraftOutputs": true,
"avoidMarshalInputs": true,
"outModifiers": {
"isSimplified": true,
"isReversed": false,
"dataMapping": "Graft",
"expression": "x * 2"
}
}
}
}
}Extension keys:
gh.csharp— C# Script componentgh.python— Python 3 Script componentgh.ironpython— IronPython 2 Script component
Extension properties:
| Property | Type | Required | Description |
|---|---|---|---|
code |
string | Yes | Script source code |
showStandardOutput |
boolean | No | Whether to show the "out" parameter (default: true) |
avoidMarshalGuids |
boolean | No | "Avoid Marshalling Output Guids" — true when enabled (default: false) |
avoidGraftOutputs |
boolean | No | "Avoid Grafting Output Lines" — true when enabled (default: false) |
avoidMarshalInputs |
boolean | No | "Avoid Marshalling Inputs" — true when enabled (default: false) |
outModifiers |
object | No | Modifiers for the "out" parameter (see below) |
Out Parameter Modifiers:
The outModifiers object captures modifiers for the "out" standard output parameter:
| Property | Type | Description |
|---|---|---|
isSimplified |
boolean | Simplify output data tree |
isReversed |
boolean | Reverse output data tree |
dataMapping |
string | Data mapping mode: "None", "Flatten", or "Graft" |
expression |
string | Expression applied to the output |
Notes:
- Marshalling options (
avoidMarshalGuids,avoidGraftOutputs,avoidMarshalInputs) are only available on C#, Python 3, and IronPython 2 components (those implementingIScriptComponent) - Default value for all marshalling options is
false(marshalling active). Only storetruevalues (when "Avoid" is enabled). - The "out" parameter is only present when
showStandardOutputistrue
VB Script components have three code sections:
{
"name": "VB Script",
"componentState": {
"extensions": {
"gh.vbscript": {
"vbCode": {
"imports": "Imports System.Math",
"script": "A = Sin(x)",
"additional": "' Helper functions here"
}
}
}
}
}Old GhPython script components (ZuiPythonComponent from GhPython.dll) store their code in the componentState.extensions object under the gh.ghpython key. This covers:
- The generic GhPython Script component from the Grasshopper toolbar.
- Ladybug Tools components (LB Hourly Plot, LB Sunpath, etc.).
- Honeybee, Dragonfly, and any other plugin that ships pre-configured
ZuiPythonComponentinstances.
Unlike Rhino 8 script components (C#, Python 3, IronPython 2) which implement IScriptComponent, old GhPython components do not expose that interface. Marshalling options (avoidMarshalGuids, avoidGraftOutputs, avoidMarshalInputs) are therefore not applicable.
{
"name": "LB Hourly Plot",
"library": "Ladybug",
"componentGuid": "410755b1-224a-4c1e-a407-bf32fb45ea7e",
"id": 1,
"pivot": "100,200",
"inputSettings": [
{
"parameterName": "_data",
"access": "list"
},
{
"parameterName": "_base_pt_"
}
],
"outputSettings": [
{
"parameterName": "mesh"
},
{
"parameterName": "legend"
}
],
"componentState": {
"extensions": {
"gh.ghpython": {
"code": "# Ladybug: A Plugin for Environmental Analysis (GPL)\n# ...\ntry:\n from ladybug_rhino.grasshopper import ...\nexcept ImportError as e:\n raise ImportError(...)",
"showStandardOutput": true
}
}
}
}Extension key: gh.ghpython
Extension properties:
| Property | Type | Required | Description |
|---|---|---|---|
code |
string | Yes | Python (IronPython) script code |
showStandardOutput |
boolean | No | Whether the out standard output parameter is visible (default: true) |
outModifiers |
object | No | Modifiers for the out parameter (same shape as section 7.4) |
Notes:
- For Ladybug/Honeybee components the
codeproperty captures the embedded script for documentation and AI understanding. During deserialization on a machine where the plugin is installed,AddedToDocumentmay reinitialize the component from the plugin's own script files. - The
inputSettingsandoutputSettingsarrays capture script parameter details (access mode, variable names, type hints) the same way as section 7.4. - Marshalling options are not available on old GhPython components; do not include
avoidMarshalGuids,avoidGraftOutputs, oravoidMarshalInputs.
Scribble geometry is defined by three corner offsets relative to the component pivot: A (top-left origin), B (top-right), and D (bottom-left). Corner C is derived as B + D - A (parallelogram rule). This minimal representation preserves rotation.
{
"name": "Scribble",
"componentState": {
"extensions": {
"gh.scribble": {
"text": "Design Notes",
"fontFamily": "Arial",
"fontSize": 14,
"fontStyle": "Bold",
"corners": ["0,0", "200,0", "0,100"]
}
}
}
}| Property | Type | Required | Description |
|---|---|---|---|
text |
string | Yes | Scribble text content |
corners |
array of 3 strings | Yes | Corner offsets relative to pivot as "x,y" pairs: [A, B, D]. Corner C = B + D − A. |
fontFamily |
string | No | Font family name (default: system default) |
fontSize |
number | No | Font size in points (default: 12) |
fontStyle |
string | No | Font style: Regular, Bold, Italic, BoldItalic (default: Regular) |
GhJSON documents SHOULD validate against the JSON Schema at:
https://architects-toolkit.github.io/ghjson-spec/schema/v1.0/ghjson.schema.json
Beyond schema validation, implementations SHOULD verify:
- Unique IDs: All component
idvalues are unique - Valid references: All connection endpoint
idvalues reference existing components - Valid parameter names: Connection
paramNamevalues exist on referenced components - Group membership: All group
membersreference existing component IDs
When deserializing, implementations MAY additionally verify:
- Component existence: The
componentGuidornamematches an installed component - Type compatibility: Connected parameter types are compatible
- Plugin dependencies: Required plugins are installed
{
"components": [
{
"name": "Number Slider",
"instanceGuid": "11111111-1111-1111-1111-111111111111",
"id": 1,
"pivot": "100,100",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "5<0~10>"
}
}
}
}
]
}{
"schema": "1.0",
"components": [
{
"name": "Number Slider",
"instanceGuid": "11111111-1111-1111-1111-111111111111",
"id": 1,
"pivot": "100,100",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "5<0~10>"
}
}
}
},
{
"name": "Number Slider",
"instanceGuid": "22222222-2222-2222-2222-222222222222",
"id": 2,
"pivot": "100,150",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "3<0,10>"
}
}
}
},
{
"name": "Addition",
"componentGuid": "a0d62394-a118-422d-abb3-6af115c75b25",
"instanceGuid": "33333333-3333-3333-3333-333333333333",
"id": 3,
"pivot": "300,125"
},
{
"name": "Panel",
"instanceGuid": "44444444-4444-4444-4444-444444444444",
"id": 4,
"pivot": "500,125"
}
],
"connections": [
{ "from": { "id": 1, "paramName": "Number" }, "to": { "id": 3, "paramName": "A" } },
{ "from": { "id": 2, "paramName": "Number" }, "to": { "id": 3, "paramName": "B" } },
{ "from": { "id": 3, "paramName": "Result" }, "to": { "id": 4, "paramName": "Input" } }
]
}{
"schema": "1.0",
"metadata": {
"description": "Simple addition example",
"author": "GhJSON Team",
"created": "2026-01-11T10:00:00Z"
},
"components": [
{
"name": "Number Slider",
"instanceGuid": "11111111-1111-1111-1111-111111111111",
"id": 1,
"pivot": "100,100",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "5<0~10>"
}
}
}
},
{
"name": "Number Slider",
"instanceGuid": "22222222-2222-2222-2222-222222222222",
"id": 2,
"pivot": "100,150",
"componentState": {
"extensions": {
"gh.numberslider": {
"value": "3<0~10>"
}
}
}
},
{
"name": "Addition",
"instanceGuid": "33333333-3333-3333-3333-333333333333",
"id": 3,
"pivot": "300,125"
}
],
"connections": [
{ "from": { "id": 1, "paramName": "Number" }, "to": { "id": 3, "paramName": "A" } },
{ "from": { "id": 2, "paramName": "Number" }, "to": { "id": 3, "paramName": "B" } }
],
"groups": [
{
"instanceGuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"name": "Inputs",
"color": "argb:255,200,220,255",
"members": [1, 2]
}
]
}The recommended MIME type for GhJSON files is:
application/vnd.grasshopper.ghjson+json
The GhJSON schema is registered at:
- GitHub: https://github.com/architects-toolkit/ghjson-spec
- Schema URL: https://architects-toolkit.github.io/ghjson-spec/schema/v1.0/ghjson.schema.json
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2026-01-11 | Initial specification |