docgen/lib/spec/spec.go (48 lines of code) (raw):
package spec
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"github.com/GoogleCloudPlatform/runtimes-common/docgen/lib/proto"
"github.com/ghodss/yaml"
"github.com/golang/protobuf/jsonpb"
)
// TODO: Add validations for proto fields.
// FromYamlFile parses a YAML file into Document pb.
func FromYamlFile(filename string) (*proto.Document, error) {
bytesData, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return FromYamlBytes(bytesData)
}
// FromYamlBytes parses a YAML content into Document pb.
func FromYamlBytes(bytesData []byte) (doc *proto.Document, err error) {
doc = &proto.Document{}
jsonData, err := yaml.YAMLToJSON(bytesData)
if err != nil {
return
}
jsonData = cleanUpJson(jsonData)
// Converts JSON to proto.
unmarshaler := &jsonpb.Unmarshaler{}
err = unmarshaler.Unmarshal(bytes.NewBuffer(jsonData), doc)
return doc, err
}
// cleanUpJson removes top level fields with names starting with underscores.
// These fields are intended as helpers in the YAML file.
// We have to do this because the unmarshaling to pb is strict on
// unknown fields.
func cleanUpJson(jsonData []byte) []byte {
var doc interface{}
json.Unmarshal(jsonData, &doc)
switch d := doc.(type) {
case map[string]interface{}:
result := map[string]interface{}{}
for key, value := range d {
if !strings.HasPrefix(key, "_") {
result[key] = value
}
}
doc = result
}
r, err := json.Marshal(&doc)
if err != nil {
panic(fmt.Sprintf("Unexpected failure when marshaling back to JSON: %v", err))
}
return r
}