{"id":5557,"library":"zcbor","title":"zcbor - CDDL Code Generation and Data Validation","description":"zcbor is a Python library for code generation and data validation based on CDDL (Concise Data Definition Language) schemas. It enables developers to generate Python code for encoding and decoding CBOR (Concise Binary Object Representation) data, ensuring compliance with specified CDDL schemas. The library is currently at version 0.9.1 and receives updates periodically, with significant releases often including migration guides for breaking changes.","status":"active","version":"0.9.1","language":"en","source_language":"en","source_url":"https://github.com/NordicSemiconductor/zcbor","tags":["CBOR","CDDL","serialization","deserialization","code-generation","data-validation","schema"],"install":[{"cmd":"pip install zcbor","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Required for parsing CDDL schemas.","package":"pycddl"},{"reason":"Underpins CBOR encoding and decoding operations.","package":"cbor2"},{"reason":"Used for templating during Python code generation.","package":"Jinja2"},{"reason":"Used for internal configuration loading within the tool.","package":"toml"}],"imports":[{"note":"Entry point for programmatic code generation using a CDDL schema. Typically invoked via `python -m zcbor.main`.","symbol":"cli","correct":"from zcbor.main import cli"},{"note":"These functions are for direct CBOR encoding/decoding without CDDL schema validation. For CDDL-schema-driven operations, use the code generated by `zcbor.main`.","symbol":"encode, decode","correct":"from zcbor.zcbor import encode, decode"}],"quickstart":{"code":"import os\nimport subprocess\nimport sys\nimport shutil\n\n# 1. Define a simple CDDL schema in a temporary file\ncddl_schema_content = \"\"\"\nmy_map = {\n    ? \"label\" => tstr,\n    ? \"value\" => int,\n}\n\"\"\"\nschema_file = \"my_schema.cddl\"\nwith open(schema_file, \"w\") as f:\n    f.write(cddl_schema_content)\n\noutput_dir = \"generated_code\"\n# Clean up previous runs if any\nif os.path.exists(output_dir):\n    shutil.rmtree(output_dir)\nos.makedirs(output_dir, exist_ok=True)\n\nprint(f\"Generating code from {schema_file} into {output_dir}...\")\n# 2. Run zcbor to generate Python code using the command-line interface\ntry:\n    # Use sys.executable to ensure the correct Python environment's zcbor is used\n    result = subprocess.run(\n        [sys.executable, \"-m\", \"zcbor.main\", schema_file, output_dir],\n        capture_output=True,\n        check=True,\n        text=True\n    )\n    print(\"Code generation successful.\")\nexcept subprocess.CalledProcessError as e:\n    print(f\"Error during code generation: {e}\")\n    print(\"STDERR:\", e.stderr)\n    sys.exit(1)\n\n# Add the output directory to the Python path to import generated modules\nsys.path.insert(0, output_dir)\n\ntry:\n    # 3. Import from the generated code and use encode/decode\n    # The generated module name will typically be the CDDL filename without extension, lowercased.\n    # Function names are snake_case from v0.9.0 onwards.\n    from my_schema import my_map_encode, my_map_decode\n\n    data = {\"label\": \"test\", \"value\": 123}\n    print(f\"Original data: {data}\")\n\n    encoded_cbor = my_map_encode(data)\n    print(f\"Encoded CBOR (hex): {encoded_cbor.hex()}\")\n\n    decoded_data, _ = my_map_decode(encoded_cbor) # decode returns (data, remaining_bytes)\n    print(f\"Decoded data: {decoded_data}\")\n\n    assert data == decoded_data\n    print(\"Encoding and decoding successful and data matches.\")\n\nexcept ImportError as e:\n    print(f\"Could not import generated module: {e}\")\n    print(\"Ensure zcbor.main successfully generated 'my_schema.py' in the 'generated_code' directory.\")\nexcept Exception as e:\n    print(f\"An error occurred during encoding/decoding: {e}\")\nfinally:\n    # Clean up temporary files and directories\n    if os.path.exists(schema_file):\n        os.remove(schema_file)\n    if os.path.exists(output_dir):\n        shutil.rmtree(output_dir)\n    # Remove from sys.path\n    if output_dir in sys.path:\n        sys.path.remove(output_dir)","lang":"python","description":"This quickstart demonstrates how to define a simple CDDL schema, use the `zcbor` command-line tool to generate Python encoding/decoding functions, and then import and use these generated functions to serialize and deserialize data according to the schema."},"warnings":[{"fix":"Change `pip install cddl-gen` to `pip install zcbor`. Update old import statements or command-line invocations accordingly, noting that internal module structures also changed.","message":"The library was renamed from `cddl-gen` to `zcbor` starting with version 0.4.0. Users upgrading from `cddl-gen` will need to update their `pip install` commands and import paths.","severity":"breaking","affected_versions":"< 0.4.0"},{"fix":"Update your `zcbor.main` command-line invocations from `python -m zcbor.main <OUTPUT_DIRECTORY> <CDDL_FILE_PATH>` to `python -m zcbor.main <CDDL_FILE_PATH> <OUTPUT_DIRECTORY>`.","message":"In version 0.8.0, the order of command-line arguments for `zcbor.main` was swapped. Previously (pre-0.8.0), it expected `output_path` then `input_path` (CDDL file). It now expects `input_path` (CDDL file) then `output_path`.","severity":"breaking","affected_versions":"0.8.0+"},{"fix":"Update calls to generated functions in your application code. For example, `MyMapEncode(...)` becomes `my_map_encode(...)`. Refer to the 0.9.0 migration guide for details.","message":"As of version 0.9.0, the names of the generated encode/decode functions in the output Python files have changed from `CamelCaseEncode`/`CamelCaseDecode` to `snake_case_encode`/`snake_case_decode`.","severity":"breaking","affected_versions":"0.9.0+"},{"fix":"Replace usages of `any` in your CDDL schemas with more specific types or alternative CDDL constructs that precisely define the expected data structure. If flexibility is required, handle the `any` type manually outside of the generated code.","message":"Starting from version 0.9.0, the `any` type in CDDL schemas is explicitly unsupported and will cause compilation errors. This change improves type safety and generated code quality.","severity":"breaking","affected_versions":"0.9.0+"}],"env_vars":null,"last_verified":"2026-04-13T00:00:00.000Z","next_check":"2026-07-12T00:00:00.000Z"}