Ben Traje
← Back to maya

Export Maya Rig Hierarchies to JSON with Python

17 Sep 26 (1mo ago)

When you're dealing with massive character rigs, sometimes you need to get the DAG hierarchy out of Maya and into a readable format for custom tools or external processing.

Dumping your scene into a clean JSON file makes life a lot easier. Here is a straightforward Python setup to grab your node hierarchy, filter out the clutter, and export it.

The Basic Script: Full Scene Export

This first version grabs every DAG object in your scene. To keep the data clean, it actively filters out shape nodes, focusing only on the transforms and joints. It maps out the immediate parent and children for each node, then dumps everything to a JSON file on your drive.

#save flat hierarchy:

import json
import os
import maya.cmds as cmds

def save_flat_hierarchy_to_d():
    # 1. Define the output file path
    output_path = r"D:\PANDA_RTA_new.json"
    
    # 2. Gather all DAG objects (transforms, joints, etc.)
    all_nodes = cmds.ls(dag=True, long=True)
    flat_hierarchy = []

    print("Gathering scene hierarchy data...")

    for node in all_nodes:
        # Filter out shape nodes to keep the rig data clean
        if cmds.nodeType(node, isTypeName='shape'):
            continue

        # Get immediate parent
        parent_list = cmds.listRelatives(node, parent=True)
        parent_name = parent_list[0] if parent_list else None
        
        # Get immediate children and filter out their shape nodes
        children_list = cmds.listRelatives(node, children=True) or []
        children_names = [c for c in children_list if not cmds.nodeType(cmds.ls(c, long=True)[0], isTypeName='shape')]

        # Build the data dictionary
        node_data = {
            "name": cmds.ls(node)[0],
            "full_path": node,
            "type": cmds.nodeType(node),
            "parent": parent_name,
            "children": children_names
        }
        
        flat_hierarchy.append(node_data)

    # 3. Write the JSON file to the D:\ drive
    try:
        with open(output_path, 'w', encoding='utf-8') as json_file:
            json.dump(flat_hierarchy, json_file, indent=4)
        print("Success! JSON file successfully saved to: {}".format(output_path))
    except IOError as e:
        print("Error: Could not write file to D:\\. Make sure the drive exists and you have write permissions.")
        print(e)

# Run the script
save_flat_hierarchy_to_d()

The Updated Script: Targeting a Specific Root

Exporting the whole scene isn't always ideal. If you just want to target a specific rig group or a root joint (like Panda_Root), you need a way to filter descendants.

This updated version introduces a parent_beg parameter. If you pass a node name to it, the script recursively grabs only that node and its descendants using the ad=True flag in listRelatives. If you leave it blank, it falls back to grabbing the entire scene.

#updated flat hierarchy:

import json
import os
import maya.cmds as cmds

def save_flat_hierarchy_to_d(parent_beg=None):
    """
    Saves Maya scene hierarchy data to a JSON file.
    
    :param parent_beg: Optional. The name or path of a parent node. 
                       If provided, only this node and its descendants are exported.
                       If None, the entire scene is exported.
    """
    # 1. Define the output file path
    output_path = r"D:\panda_root_new.json"
    
    # 2. Gather target DAG objects based on the parent_beg setting
    if parent_beg:
        # Verify the specified parent actually exists
        if not cmds.objExists(parent_beg):
            print(f"Error: The specified parent node '{parent_beg}' does not exist.")
            return
        
        # Get the full path of the parent node to avoid ambiguity
        parent_full_path = cmds.ls(parent_beg, long=True)[0]
        
        # Gather all descendants (children, grandchildren, etc.)
        # ad=True (allDescendents) recursively grabs everything below it
        descendants = cmds.listRelatives(parent_full_path, ad=True, fullPath=True) or []
        
        # Combine the parent itself and all its descendants into our target list
        all_nodes = [parent_full_path] + descendants
        print(f"Gathering hierarchy data under parent: {parent_beg}...")
    else:
        # Fallback to the entire scene if no parent is specified
        all_nodes = cmds.ls(dag=True, long=True)
        print("Gathering entire scene hierarchy data...")

    flat_hierarchy = []

    for node in all_nodes:
        # Filter out shape nodes to keep the rig data clean
        if cmds.nodeType(node, isTypeName='shape'):
            continue

        # Get immediate parent
        parent_list = cmds.listRelatives(node, parent=True, fullPath=True)
        parent_name = parent_list[0] if parent_list else None
        
        # Get immediate children and filter out their shape nodes
        children_list = cmds.listRelatives(node, children=True, fullPath=True) or []
        children_names = [
            c for c in children_list 
            if not cmds.nodeType(c, isTypeName='shape')
        ]

        # Build the data dictionary
        node_data = {
            "name": node.split("|")[-1], # Clean short name
            "full_path": node,
            "type": cmds.nodeType(node),
            "parent": parent_name,
            "children": children_names
        }
        
        flat_hierarchy.append(node_data)

    # 3. Write the JSON file to the D:\ drive
    try:
        with open(output_path, 'w', encoding='utf-8') as json_file:
            json.dump(flat_hierarchy, json_file, indent=4)
        print("Success! JSON file successfully saved to: {}".format(output_path))
    except IOError as e:
        print("Error: Could not write file to D:\\. Make sure the drive exists and you have write permissions.")
        print(e)

# --- How to run it ---

# Example 1: Target only "root" and everything beneath it
save_flat_hierarchy_to_d(parent_beg="Panda_Root")

# Example 2: Target the whole scene (just like before)
# save_flat_hierarchy_to_d()