mardi 20 juillet 2021

Structure detection in golang [duplicate]

I want to parse a string to struct using reflection. But problem is that we have many different structs, which vary in value of "Type" field. First of all I convert string to map of key-values as following:

input string:

"[6001]\ntype = endpoint\ncontext = internal\ndisallow = all\nallow = ulaw\nallow = law\naors = 6001\nauth = auth6001"

converted to map:

map[Name:6001 allow:ulaw law aors:6001 auth:auth6001 context:internal disallow:all type:endpoint]

Before reflection we have to choose which of structs to create. Does it exist a way to choose it without hardcoding (writing special func for each structure)?

type All struct{
    A 
    B
    C
}
type A struct {
    Type string
}
type B struct {
    Type string
}
type C struct {
    Name     string
    Type     string
    Context  string
    Disallow []string
    Allow    []string
    Aors     string
    Auth     string
}
input := "[6001]\ntype = endpoint\ncontext = internal\ndisallow = all\nallow = ulaw\nallow = law\naors = 6001\nauth = auth6001"
func getMap(input string) map[string]string {
    input := "[6001]\ntype = endpoint\ncontext = internal\ndisallow = all\nallow = ulaw\nallow = law\naors = 6001\nauth = auth6001"
    // remove spaces
    input = regexp.MustCompile(`\p{Z}|(\;\S+)`).ReplaceAllString(ex, "")
    rows := strings.Split(ex, "\n")
    m := make(map[string]string)
    // filling "Name" field
    m["Name"] = strings.Trim(regexp.MustCompile(`\[[a-zA-Z0-9]{1,}\]`).FindString(ex), "[]")
    // filling other fields
    for i := 1; i < len(rows); i++ {
        kv := strings.Split(rows[i], "=") // пара ключ-значение
        if _, ok := m[kv[0]]; ok {
            m[kv[0]] = fmt.Sprintf("%s %s", m[kv[0]], kv[1])
        } else {
            m[kv[0]] = kv[1]
        }
    }
    return m
}
    
func (a *All) fillStruct(m map[string]string) {
    a.C = Example{} // it should check m["type"] and then create the corresponding structure
    val := reflect.ValueOf(&E).Elem()
    for i := 0; i < val.NumField(); i++ {
        f := val.Field(i)
        name := under_score(val.Type().Field(i).Name) // "underscore" converts CamelCase to under_score
        if _, ok := m[name]; !ok {
            fmt.Println(name, ok)
            continue
        }
        switch f.Kind() {
        case reflect.Slice:
            f.Set(reflect.ValueOf(strings.Split(m[name], " ")))
        case reflect.String:
            f.SetString("test")
        default:
            log.Println("unsupported field type", f.Kind())
        }
    }
}




Aucun commentaire:

Enregistrer un commentaire