Serializers implement the Serializer
interface. These simple objects
have two tasks in life:
-
Serialize to another format: This means taking a protobom, reading its data and returning a new SBOM data structure in a standard format (CycloneDX or SPDX). This is what will be known in these docs as serialization. Any data loss or modification due to the conversion process occurs during serialization.
-
Rendering new documents: Once the protobom has been serialized to another format, the serializer needs to know how to write the SBOM (now in SPDX or CDX) to an
io.Writer
(a file, network stream, etc). The serializer takes the standard SBOM as aninterface{}
so it needs to know how to cast the SBOM into the expected type.
Both tasks of the serializer are invoked by the Writer
object when calling
the WriteStream()
function.
Each serializer is tasked with turning a protobom to a standard SBOM object. In general, serializers will be in charge of one format-version-encoding combination. For example, one serializer should handle CycloneDX + 1.4 + JSON. There is opportunity for code reuse and optimization but in general, the idea is that one serializer type handles a single format.
Implementing a new serializer means writing two methods: Serialize()
and
Render()
. The first one creates a standard SBOM object from a protobom and the
second writes the SBOM object in the serializer's encoding (JSON, tag-value, XML,
etc) to any stream that implements io.Writer
.
The initial POC of protobom shows a simple example on how to write a serializer:
- A type is defined to implement the interface (
SerializerCDX14
). - It
defines the Serialize
method:- The basic job of this function is creating a standard SBOM object (a CycloneDX 1.4 document in this case) and populate its fields from the protobom data.
- The main parts to note in this example are how it first creates all the CycloneDX components from the protobom Nodes. Then, it reads the edges from the graph and based on the relationship kind, either assigns the nodes to the components tree or just notes them on the dependency tree.
- Note that the code has notes on where data degradation or loss is done (example 1 example 2 ). These comments need to be documented and will become the degradation stargey doc that users can then read to understand when data loss due to translation occurs.
- Finally, it implements the
Render()
method. In the POC the method is very simple, it just creates a json.Encoder() and writes the cast SBOM object to the writer.