Skip to content

Serializing APIs¤

Griffe can be used to load API data and output it as JSON on standard output or in writable files. An example of what real data looks like can be found here: Griffe's full JSON dump. We also provide a JSON schema.

Command-line¤

The easiest way to load and serialize API data is to use the command-line tool:

$ griffe dump httpx fastapi
{
  "httpx": {
    "name": "httpx",
    ...
  },
  "fastapi": {
    "name": "fastapi",
    ...
  }
}

It will output a JSON-serialized version of the packages API data.

Try it out on Griffe itself:

$ griffe dump griffe
{
  "griffe": {
    "name": "griffe",
    ...
  }
}

To output in a file instead of standard output, use the -o, --output option:

$ griffe dump griffe -o griffe.json

If you load multiple packages' signatures, you can dump each in its own file with a templated filepath:

$ griffe dump griffe -o './dumps/{package}.json'

By default, Griffe will search in sys.path, so if you installed it through pipx, there are few chances it will find your packages. To explicitly specify search paths, use the -s, --search <PATH> option. You can use it multiple times. You can also add the search paths to the PYTHONPATH environment variable. If Griffe can't find the packages, it will fail with a ModuleNotFoundError.

See all the options for the dump command in the CLI reference.

Python API¤

If you have read through the Navigating chapter, you know about our five data models for modules, classes, functions, attributes and aliases. Each one of these model provide the two following methods:

  • as_json, which allows to serialize an object into JSON,
  • from_json, which allows to load JSON back into a model instance.

These two methods are convenient wrappers around our JSON encoder and JSON decoder. The JSON encoder and decoder will give you finer-grain control over what you serialize or load, as the methods above are only available on data models, and not on sub-structures like decorators or parameters.

Under the hood, as_json just calls as_dict, which converts the model instance into a dictionary, and then serialize this dictionary to JSON.

When serializing an object, by default the JSON will only contain the fields required to load it back to a Griffe model instance. If you are not planning on loading back the data into our data models, or if you want to load them in a different implementation which is not able to infer back all the other fields, you can choose to serialize every possible field. We call this a full dump, and it is enabled with the full option of the encoder or the as_json method.

Schema¤

For anything automated, we suggest relying on our JSON schema.

When serializing multiple packages with the dump command, you get a map with package names as keys. Map values are the serialized objects (modules, classes, functions, etc.). They are maps too, with field names and values as key-value pairs.

For example:

{
  "kind": "class",
  "name": "Expr",
  "lineno": 82,
  "endlineno": 171,
  "docstring": {
    "value": "Base class for expressions.",
    "lineno": 84,
    "endlineno": 84
  },
  "labels": [
    "dataclass"
  ],
  "members": [
    ...
  ],
  "bases": [],
  "decorators": [
    {
      "value": {
        "name": "dataclass",
        "cls": "ExprName"
      },
      "lineno": 82,
      "endlineno": 82
    }
  ]
}

The members value, truncated here, just repeats the pattern: it's an array of maps. We use an array for members instead of a map to preserve order, which could be important to downstream tools.

The other fields do not require explanations, except maybe for expressions. You will sometimes notice deeply nested structures with cls keys. These are serialized Griffe expressions. They represent actual code.

Next steps¤

That's it! There is not much to say about serialization. We are interested in getting your feedback regarding serialization as we didn't see it being used a lot. Next you might be interested in learning