sg/internal/project/reader.go (32 lines of code) (raw):

package project import ( "encoding/json" "fmt" "io" "os" "gopkg.in/yaml.v3" ) // ReadFromYAML reads a project specification from YAML. func ReadFromYAML(src io.Reader) (Spec, error) { // NOTE: since we want to support YAML anchors and mixing string list and string map, // therefore, we firstly use yaml.Decoder to resolve the anchors and encode // the spec to a untyped object. Then, we use json.Unmarshal to decode the resolved // values. Finally, the mixed string list and string map will be decoded via strListOrMap. var untypedObj any yamlDecoder := yaml.NewDecoder(src) if err := yamlDecoder.Decode(&untypedObj); err != nil { return Spec{}, fmt.Errorf("decode yaml: %w", err) } resolvedJSON, err := json.Marshal(untypedObj) if err != nil { return Spec{}, fmt.Errorf("resolve to json: %w", err) } var rv Spec if err := json.Unmarshal(resolvedJSON, &rv); err != nil { return Spec{}, fmt.Errorf("decode json: %w", err) } return rv, nil } // ReadFromFile reads a project specification from a file. func ReadFromFile(p string) (Spec, error) { f, err := os.Open(p) if err != nil { return Spec{}, fmt.Errorf("read file %q: %w", p, err) } defer f.Close() return ReadFromYAML(f) }