mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-08 04:20:17 +00:00
259 lines
9.0 KiB
Go
259 lines
9.0 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/pb33f/libopenapi/datamodel/low"
|
|
"gopkg.in/yaml.v3"
|
|
"reflect"
|
|
"strconv"
|
|
)
|
|
|
|
func BuildModel(node *yaml.Node, model interface{}) error {
|
|
v := reflect.ValueOf(model).Elem()
|
|
for i := 0; i < v.NumField(); i++ {
|
|
|
|
fName := v.Type().Field(i).Name
|
|
|
|
// we need to find a matching field in the YAML, the cases may be off, so take no chances.
|
|
cases := []Case{PascalCase, CamelCase, ScreamingSnakeCase,
|
|
SnakeCase, KebabCase, RegularCase}
|
|
|
|
var vn, kn *yaml.Node
|
|
for _, tryCase := range cases {
|
|
kn, vn = FindKeyNode(ConvertCase(fName, tryCase), node.Content)
|
|
if vn != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
if vn == nil {
|
|
// no point in going on.
|
|
continue
|
|
}
|
|
|
|
field := v.FieldByName(fName)
|
|
kind := field.Kind()
|
|
switch kind {
|
|
case reflect.Struct, reflect.Slice, reflect.Map:
|
|
err := SetField(field, vn, kn)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
default:
|
|
fmt.Printf("Unsupported type: %v", v.Field(i).Kind())
|
|
break
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) error {
|
|
switch field.Type() {
|
|
|
|
case reflect.TypeOf(map[string]low.ObjectReference{}):
|
|
if valueNode != nil {
|
|
if IsNodeMap(valueNode) {
|
|
if field.CanSet() {
|
|
items := make(map[string]low.ObjectReference)
|
|
var currentLabel string
|
|
for i, sliceItem := range valueNode.Content {
|
|
if i%2 == 0 {
|
|
currentLabel = sliceItem.Value
|
|
continue
|
|
}
|
|
var decoded map[string]interface{}
|
|
err := sliceItem.Decode(&decoded)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
items[currentLabel] = low.ObjectReference{
|
|
Value: decoded,
|
|
Node: sliceItem,
|
|
}
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
|
|
case reflect.TypeOf(low.ObjectReference{}):
|
|
if valueNode != nil {
|
|
var decoded map[string]interface{}
|
|
err := valueNode.Decode(&decoded)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if IsNodeMap(valueNode) {
|
|
if field.CanSet() {
|
|
or := low.ObjectReference{Value: decoded, Node: valueNode}
|
|
field.Set(reflect.ValueOf(or))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.ObjectReference{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.ObjectReference
|
|
for _, sliceItem := range valueNode.Content {
|
|
var decoded map[string]interface{}
|
|
err := sliceItem.Decode(&decoded)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
items = append(items, low.ObjectReference{
|
|
Value: decoded,
|
|
Node: sliceItem,
|
|
})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[string]{}):
|
|
if valueNode != nil {
|
|
if IsNodeStringValue(valueNode) {
|
|
if field.CanSet() {
|
|
nr := low.NodeReference[string]{Value: valueNode.Value, Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[bool]{}):
|
|
if valueNode != nil {
|
|
if IsNodeBoolValue(valueNode) {
|
|
if field.CanSet() {
|
|
bv, _ := strconv.ParseBool(valueNode.Value)
|
|
nr := low.NodeReference[bool]{Value: bv, Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[int]{}):
|
|
if valueNode != nil {
|
|
if IsNodeIntValue(valueNode) {
|
|
if field.CanSet() {
|
|
fv, _ := strconv.Atoi(valueNode.Value)
|
|
nr := low.NodeReference[int]{Value: fv, Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[int64]{}):
|
|
if valueNode != nil {
|
|
if IsNodeIntValue(valueNode) {
|
|
if field.CanSet() {
|
|
fv, _ := strconv.Atoi(valueNode.Value)
|
|
nr := low.NodeReference[int64]{Value: int64(fv), Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[float32]{}):
|
|
if valueNode != nil {
|
|
if IsNodeFloatValue(valueNode) {
|
|
if field.CanSet() {
|
|
fv, _ := strconv.ParseFloat(valueNode.Value, 32)
|
|
nr := low.NodeReference[float32]{Value: float32(fv), Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf(low.NodeReference[float64]{}):
|
|
if valueNode != nil {
|
|
if IsNodeFloatValue(valueNode) {
|
|
if field.CanSet() {
|
|
fv, _ := strconv.ParseFloat(valueNode.Value, 64)
|
|
nr := low.NodeReference[float64]{Value: fv, Node: valueNode}
|
|
field.Set(reflect.ValueOf(nr))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.NodeReference[string]{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.NodeReference[string]
|
|
for _, sliceItem := range valueNode.Content {
|
|
items = append(items, low.NodeReference[string]{Value: sliceItem.Value, Node: sliceItem})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.NodeReference[float32]{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.NodeReference[float32]
|
|
for _, sliceItem := range valueNode.Content {
|
|
fv, _ := strconv.ParseFloat(sliceItem.Value, 32)
|
|
items = append(items, low.NodeReference[float32]{Value: float32(fv), Node: sliceItem})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.NodeReference[float64]{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.NodeReference[float64]
|
|
for _, sliceItem := range valueNode.Content {
|
|
fv, _ := strconv.ParseFloat(sliceItem.Value, 64)
|
|
items = append(items, low.NodeReference[float64]{Value: fv, Node: sliceItem})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.NodeReference[int]{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.NodeReference[int]
|
|
for _, sliceItem := range valueNode.Content {
|
|
iv, _ := strconv.Atoi(sliceItem.Value)
|
|
items = append(items, low.NodeReference[int]{Value: iv, Node: sliceItem})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case reflect.TypeOf([]low.NodeReference[bool]{}):
|
|
if valueNode != nil {
|
|
if IsNodeArray(valueNode) {
|
|
if field.CanSet() {
|
|
var items []low.NodeReference[bool]
|
|
for _, sliceItem := range valueNode.Content {
|
|
bv, _ := strconv.ParseBool(sliceItem.Value)
|
|
items = append(items, low.NodeReference[bool]{Value: bv, Node: sliceItem})
|
|
}
|
|
field.Set(reflect.ValueOf(items))
|
|
}
|
|
}
|
|
}
|
|
break
|
|
default:
|
|
m := field.Type()
|
|
fmt.Printf("error, unknown type!!! %v", m)
|
|
return fmt.Errorf("unknown type, cannot parse: %v", m)
|
|
}
|
|
return nil
|
|
}
|