Skip to content

Export the top navigation bar structure to a JSON file.

Walks every navigation node (top-level and sub-menus, recursively via get_all_nodes) with a progress bar, then exports the loaded tree through the collection's to_json() — the pipeline serialization recurses into each node's loaded Children.

A Python port of PnP's spo-export-topnavbar-including-translations script sample (without the multilingual title resources).

Reference

View source

import argparse
import json

from office365.runtime.operations import Progress
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.navigation.nodes.node import NavigationNode
from tests.settings import cert_path, cert_thumbprint, client_id, site_url, tenant


def progress_bar(description: str):
    """tqdm-backed hook — the library only needs a ``Callable[[Progress], None]``."""
    from tqdm import tqdm

    bar = tqdm(desc=description)

    def hook(p: Progress[NavigationNode]) -> None:
        bar.update(p.done - bar.n)

    return hook


def main():
    parser = argparse.ArgumentParser(description="Export the top navigation bar to JSON")
    parser.add_argument("--site-url", default=site_url, help="site URL")
    parser.add_argument("--output", default="top_navigation.json", help="output JSON file")
    parser.add_argument("--no-progress", action="store_true", help="do not show a tqdm progress bar")
    args = parser.parse_args()

    ctx = ClientContext(args.site_url).with_client_certificate(
        tenant, client_id=client_id, thumbprint=cert_thumbprint, cert_path=cert_path
    )

    hook = None if args.no_progress else progress_bar("Scanning navigation")
    nodes = ctx.web.navigation.top_navigation_bar.get_all_nodes(recursive=True, progress=hook).execute_query()
    if not nodes:
        raise SystemExit("No top navigation nodes found.")

    tree = nodes.to_json()  # recurses through each node's loaded Children
    with open(args.output, "w", encoding="utf-8") as f:
        json.dump(tree, f, indent=2)
    print(f"Exported {len(nodes)} navigation node(s) to {args.output}")


if __name__ == "__main__":
    main()

← Back to Navigation