2017-08-25 5 views
0

私はYAML設定ファイルを扱うためのコードをいくつか用意していますが、これはコントロールの型が無くなっているため、より良いやり方が必要だと感じています。ここGoで動的YAMLを構文解析する慣用方法は何ですか?

plugins: 
    taxii20: 
    default: default 
    api_roots: 
     default: 
     auth: 
      - ldap 
      - mutualtls 
     collections: 
      all: 
      selector: g.V().Save("<type>").Save("<created>").All() 
      selector_query_lang: gizmo 

そして、私の解析コードです:

ここに私のconfigファイルからの関連抜粋です

func parseTaxiiConfig() { 
    plg.ConfigMutex.Lock() 
    taxiiConfig := plg.ConfigData.Plugins["taxii20"].(map[interface{}]interface{}) 
    ConfigData = &Config{} 
    if taxiiConfig["default"] != nil { 
     ConfigData.DefaultRoot = taxiiConfig["default"].(string) 
    } 
    if taxiiConfig["api_roots"] != nil { 
     ConfigData.APIRoots = make([]model.APIRoot, 0) 
     iroots := taxiiConfig["api_roots"].(map[interface{}]interface{}) 
     for iname, iroot := range iroots { 
      root := model.APIRoot{Name: iname.(string)} 
      authMethods := iroot.(map[interface{}]interface{})["auth"].([]interface{}) 
      root.AuthMethods = make([]string, 0) 
      for _, method := range authMethods { 
       root.AuthMethods = append(root.AuthMethods, method.(string)) 
      } 
      collections := iroot.(map[interface{}]interface{})["collections"].(map[interface{}]interface{}) 
      root.Collections = make([]model.Collection, 0) 
      for icolName, icollection := range collections { 
       collection := model.Collection{Name: icolName.(string)} 
       collection.Selector = icollection.(map[interface{}]interface{})["selector"].(string) 
       collection.SelectorQueryLang = icollection.(map[interface{}]interface{})["selector_query_lang"].(string) 
       root.Collections = append(root.Collections, collection) 
      } 
      ConfigData.APIRoots = append(ConfigData.APIRoots, root) 
     } 
    } 
    plg.ConfigMutex.Unlock() 

    // debug 
    fmt.Println(ConfigData) 
} 

コードが意図したとおりに動作しますが、そこだけで非常に多くの種類のアサーションここだと私ができます私がより良い方法を見逃しているという気持ちを揺さぶる。

設定が示唆しているように、これはキャディースタイルのプラグインシステム用の設定であるため、メイン設定パーサーはプラグイン設定の形状を事前に知ることができません。設定ファイルのプラグインの部分の処理をプラグイン自体に委譲しなければなりません。

+0

実は、http://github.com/mitchellh/mapstructureでこの問題を解決するためのマイ同僚のコードの一部を発見した - 私はそれが仕事を得ることができれば、私はすぐにこの質問を更新します。 –

答えて

0

ここで私が思いついたのはこれです。はるかに読みやすい。

// Config represents TAXII 2.0 plugin structure 
type Config struct { 
    DefaultRoot string 
    APIRoots []model.APIRoot 
} 

// Intermediate config for mapstructure 
type configRaw struct { 
    DefaultRoot string    `mapstructure:"default"` 
    APIRoots map[string]apiRootRaw `mapstructure:"api_roots"` 
} 
type apiRootRaw struct { 
    AuthMethods []string     `mapstructure:"auth"` 
    Collections map[string]collectionRaw `mapstructure:"collections"` 
} 
type collectionRaw struct { 
    Selector   string `mapstructure:"selector"` 
    SelectorQueryLang string `mapstructure:"selector_query_lang"` 
} 

func parseTaxiiConfig() error { 
    plg.ConfigMutex.Lock() 
    defer plg.ConfigMutex.Unlock() 

    taxiiConfig := plg.ConfigData.Plugins["taxii20"].(map[interface{}]interface{}) 
    fmt.Println(taxiiConfig) 
    ConfigData = &Config{} 
    raw := &configRaw{} 
    err := mapstructure.Decode(taxiiConfig, raw) 
    if err != nil { 
     return err 
    } 

    ConfigData.DefaultRoot = raw.DefaultRoot 
    ConfigData.APIRoots = make([]model.APIRoot, 0) 
    for name, root := range raw.APIRoots { 
     apiRoot := model.APIRoot{Name: name} 
     apiRoot.AuthMethods = root.AuthMethods 
     apiRoot.Collections = make([]model.Collection, 0) 
     for colName, col := range root.Collections { 
      collection := model.Collection{Name: colName} 
      collection.Selector = col.Selector 
      collection.SelectorQueryLang = col.SelectorQueryLang 
      apiRoot.Collections = append(apiRoot.Collections, collection) 
     } 
     ConfigData.APIRoots = append(ConfigData.APIRoots, apiRoot) 
    } 

    return nil 
} 
関連する問題