Copyright 2025 DMTF. All rights reserved.
Python utility to convert Redfish JSON Schema into .proto definitions.
Inside the schema directory, there are JSON files which collectively define the Redfish schema.
Each file is named in the format ResourceName.v1_2_3.json, where ResourceName is the name of the
resource, and v1_2_3 is the version number. The content of these files follows the json schema
specification, and comes from the DMTF Redfish specification. Any response from a compliant
Redfish system will conform to one of these schemas. Largely, the content of these json files
are dictionaries with various fields, and sometimes nested dictionaries, which define the
structure of the resource.
The goal of this utility is to convert these JSON schemas into Protocol Buffers (.proto) definitions, which can in turn be used to generate code in various programming languages. (In my case, Go) This is made complex by the fact that the JSON schemas contain many references to other schemas. This utility will need to resolve these references and generate a .proto file for each schema, containing all the necessary protobuf "messages" and enums.
The root dictionary of each schema definition file has some standard fields:
- The "
$id" field is the unique identifier for the schema, and is used to reference the schema in other files. The Redfish spec makes this a fully qualified URL, but the spec doesn't require it. - The "
$schema" field is a link to the JSON schema version that the file conforms to. (Not used in this utility) - The "
title" field is a human-readable name for the schema, which for Redfish is roughly the same as the resource name. The most important root field is "definitions", which is another dictionary which contains the definitions of resources contained in the specific schema file. Inside the "definitions" dict is an item with the same name as the schema file. This item contains the actual schema definition for resource. Sibling to the field with the resource name are other fields which are referenced by the main definition and haven't been defined in another schema.
So for example, the meat of the "chassis" schema is at chassis_schema["definitions"]["Chassis"].
But that dict likely references other definitions, like chassis["definitions"]["Door"] or
chassis["definitions"]["IndicatorLED"], which could in turn reference a definition from another
schema. These references are made using the "$ref" field, which contains a string that is either
a fully qualified URL to another schema file, or a relative path A "$ref" to another schema looks
like "$ref": "{$id}#/definitions/{resource}/
A "$ref" to a sibling definition in the same schema looks like "$ref": "#/definitions/{resource}/"
Each schema file will map to a single .proto file, called a "package" in Protocol Buffer terms.
Inside each proto file, there will be one or more "messages" which correspond to the definitions of
resources in the schema. Each message will have fields corresponding to the properties of the
resource, and enums for any enumerated types that are referenced in the schema. The messages will
be named according to the resource name, with the version number removed, and the package name
will be the schema name with dots replaced by underscores and prefixed with "redfish.". For example,
the chassis schema would be in a package "redfish.chassis", and the main message would be "Chassis".
Note that a "message" in Protocol Buffers is similar to a "struct" in object-oriented
programming, and a resource file is similar to a "class" in object-oriented programming.
Any "$ref" fields will be resolved to the corresponding message in the same package
The general flow of the utility is as follows:
- Load all JSON schema files from the schema directory into memory.
- Begin at one of the schema files, and create the corresponding proto file.
- For each definition in the schema, create a corresponding proto message.
- For each field in the definition, create a corresponding proto field.
- For each enum in the definition, create a corresponding proto enum.
If a field is a reference to another schema, recurse into that schema.
find ./output/ -name "*.proto" ! -name "odata.proto" ! -name "Resource.proto" -deletepython src/main.pyprotoc --go-grpc_out=go-output/ --proto_path=output/ --go_out=go-output/ $(find ./output/ -name "*.proto")echo -e "module Redfish\ngo 1.24.3" > ./Redfish/go.mod