Разобрать файл yaml в предопределенную структуру в go

У меня есть несколько файлов yaml, которые нужно разобрать, и они имеют одинаковую структуру.

schema: "1.0.0"
id: test
version: "1.2.3"


dependency :
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
         properties:
             name: app
             url: appUrl

  - name: backend
    type: mongoDb
    path: be
    install:
       - name: db
         type: mongo
    provides:
       - name: api
         properties:
            url: url

Раздел схемы является обязательным для всех yaml, которые приложение должно получать всегда.

Тег зависимости может содержать от 1 до n записей с обязательными полями: имя, тип, cwd.

Тег зависимости может (или нет) содержать раздел install с name и properties, что является обязательным.

Тег зависимости может (или нет) содержать раздел provides с name, что является обязательным.

У установки могут быть свойства, и у поставок также могут быть свойства.

Я использую парсер yaml для анализа файлов, но мой вопрос в том, как в Golang я могу построить структура, что когда я разбираю документ, он автоматически заполняет основную структуру и включает подструктуры (например, разделы зависимостей/установки)

Я пробовал что-то вроде

type main struct {
    schema struct {
        schema  string
        id int
        version string
    }

    dependency struct {
        name  string
        type string
        cwd string

    install struct {
        name  string
    }


}

В разделе установки это может быть группа, тип или и то, и другое, а также может быть раздел свойств, поэтому я не уверен, как создать некоторую общую/расширяемую структуру, которую я использую для анализа документа (у документа есть закрытый список свойств , то что я поставил в примере опишу самые варианты)

Я использую эту библиотеку для анализа документа

парсер yaml

введите здесь описание изображения


person Community    schedule 11.12.2017    source источник


Ответы (1)


Ваше определение структуры должно быть примерно таким

type Yaml struct {
    Schema     string
    ID         string
    Version    string
    Dependency []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Provides []Provide
}

type Install struct {
    Name       string
    Group      string
    Type       string
    Properties Properties
}

type Properties struct {
    Name string
    URL  string
}

type Provide struct {
    Name       string
    Properties Properties
}

Вот полный пример кода:

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "gopkg.in/yaml.v2"
)

var data = `
schema: "1.0.0"
id: test
version: "1.2.3"


dependency :
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
         properties:
             name: app
             url: appUrl

  - name: backend
    type: mongoDb
    path: be
    install:
       - name: db
         type: mongo
    provides:
       - name: api
         properties:
             url: url
`

type Yaml struct {
    Schema     string
    ID         string
    Version    string
    Dependency []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Provides []Provide
}

type Install struct {
    Name       string
    Group      string
    Type       string
    Properties Properties
}

type Properties struct {
    Name string
    URL  string
}

type Provide struct {
    Name       string
    Properties Properties
}

func main() {
    y := Yaml{}

    err := yaml.Unmarshal([]byte(data), &y)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("%+v\n", y)

}

Выход

{Schema:1.0.0 ID:test Version:1.2.3 Dependency:[{Name:ui Type:runner CWD:/ui Install:[{Name:api Group:test Type: Properties:{Name:appURL:appUrl}}] Provides:[]} {Name:backend Type:mongoDb CWD: Install:[{Name:db Group: Type:mongo Properties:{Name: URL:}}] Provides:[{Name:api Properties:{Name: URL:url}}]}]}

Если вы хотите читать из файла yaml, в основной функции просто замените:

err := yaml.Unmarshal([]byte(data), &y)

с

yamlFile, err := ioutil.ReadFile("yaml_sample.yaml")
if err != nil {
    log.Printf("yamlFile.Get err   #%v ", err)
}
err = yaml.Unmarshal(yamlFile, &y)
person Vane Trajkov    schedule 11.12.2017
comment
Спасибо 1+, не могли бы вы привести пример, как бы вы проанализировали файл в ответе на эту структуру? - person ; 11.12.2017
comment
Большое спасибо, я попробовал ваш пример, и он частично работает, объекты install properties provides пусты, есть идеи? - person ; 11.12.2017
comment
Извините, это нормально, проблема связана с отладчиком кода vs, похоже, он не показывает объект в глубокой структуре... см. Мое обновление, вы не можете открыть объект массива, чтобы увидеть, что там - person ; 11.12.2017
comment
мой последний вопрос:) если вам нужно собрать эту программу golang, как бы вы структурировали проект, скажем, основная находится под rootProj-> cmd>main.go, куда вы помещаете всю «структуру» (какая папка в проекте и если вы создаете новый файл для каждого struct...) и как вы загружаете их в основной метод. большое спасибо! - person ; 11.12.2017
comment
Если приложение — это все, что указано в этом описании вопроса, вы можете сохранить все это в одном файле. Окончательный дизайн вашего приложения должен зависеть от ваших полных требований и сложности. Это похоже на другой вопрос, и он слишком общий. Не могли бы вы отделить его от другого вопроса StackOverflow и предоставить более подробную информацию. - person Vane Trajkov; 11.12.2017