J'ai récemment vu que le go yaml lib a une nouvelle version (V3)
avec les capacités nœuds (ce qui, à mon avis, est une fonctionnalité de tueur :)) qui peut aider beaucoup à modifier les yamls sans changer la structure du fichier
Mais comme il est assez récent (de la semaine dernière), je n'ai pas trouvé de documents utiles et d'exemples pour le contexte dont j'ai besoin (ajouter un nouvel objet/nœud et conserver la structure du fichier identique sans supprimer les commentaires, etc.)
ce dont j'ai besoin c'est de manipuler le fichier yaml
par exemple
disons que j'ai ce fichier yaml
version: 1
type: verbose
kind : bfr
# my list of applications
applications:
- name: app1
kind: nodejs
path: app1
exec:
platforms: k8s
builder: test
Maintenant, j'ai un objet json (par exemple avec app2
) Que je dois insérer dans le fichier existant
[
{
"comment: "Second app",
"name": "app2",
"kind": "golang",
"path": "app2",
"exec": {
"platforms": "dockerh",
"builder": "test"
}
}
]
et je dois l'ajouter au fichier yml après la première application (les applications sont un tableau d'applications)
version: 1
type: verbose
kind : bfr
# my list of applications
applications:
# First app
- name: app1
kind: nodejs
path: app1
exec:
platforms: k8s
builder: test
# Second app
- name: app2
kind: golang
path: app2
exec:
platforms: dockerh
builder: test
est-il possible d'ajouter à partir du fichier yaml le nouvel objet json? supprimer également les
J'ai également trouvé ce blog https://blog.ubuntu.com/2019/04/05/api-v3-of-the -yaml-package-for-go-is-available
Ce sont les types qui représentent l'objet
type VTS struct {
version string `yaml:"version"`
types string `yaml:"type"`
kind string `yaml:"kind,omitempty"`
apps Applications `yaml:"applications,omitempty"`
}
type Applications []struct {
Name string `yaml:"name,omitempty"`
Kind string `yaml:"kind,omitempty"`
Path string `yaml:"path,omitempty"`
Exec struct {
Platforms string `yaml:"platforms,omitempty"`
Builder string `yaml:"builder,omitempty"`
} `yaml:"exec,omitempty"`
}
mise à jour
après avoir testé la solution fournie par wiil7200
j'ai trouvé 2 problèmes
J'utilise à la fin l'écrire dans le fichier err = ioutil.WriteFile("output.yaml", b, 0644)
Et la sortie yaml a 2 problèmes.
Le tableau de l'application commence à partir des commentaires, il doit commencer par le nom
Après l'entrée
name
, la propriétékind
et toutes les autres après ne sont pas alignées sur laname
une idée de comment résoudre ces problèmes? en ce qui concerne le problème comments
, disons que je l'ai obtenu d'une autre propriété et non du json (si cela le rend plus simple)
version: 1
type: verbose
kind: bfr
# my list of applications
applications:
- # First app
name: app1
kind: nodejs
path: app1
exec:
platforms: k8s
builder: test
- # test 1
name: app2
kind: golang
path: app2
exec:
platform: dockerh
builder: test
Vous pouvez créer un nouveau nœud et l'ajouter directement au contenu, sans supprimer le nœud précédent. L'exemple suivant illustre ce point:
package main
import (
"fmt"
"log"
"gopkg.in/yaml.v3"
)
var (
sourceYaml = `version: 1
type: verbose
kind : bfr
# my list of applications
applications:
# First app
- name: app1
kind: nodejs
path: app1
exec:
platforms: k8s
builder: test
`
)
type Application struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
Path string `yaml:"path,omitempty" json:"path,omitempty"`
Exec struct {
Platforms string `yaml:"platforms,omitempty" json:"platforms,omitempty"`
Builder string `yaml:"builder,omitempty" json:"builder,omitempty"`
} `yaml:"exec,omitempty" json:"exec,omitempty"`
}
func newApplicationNode(
name string,
kind string,
path string,
platforms string,
builder string,
comment string) (*yaml.Node, error) {
app := Application{
Name: name,
Kind: kind,
Path: path,
Exec: struct {
Platforms string `yaml:"platforms,omitempty" json:"platforms,omitempty"`
Builder string `yaml:"builder,omitempty" json:"builder,omitempty"`
}{platforms, builder},
}
marshalledApp, err := yaml.Marshal(&app)
if err != nil {
return nil, err
}
node := yaml.Node{}
if err := yaml.Unmarshal(marshalledApp, &node); err != nil {
return nil, err
}
node.Content[0].HeadComment = comment
return &node, nil
}
func main() {
yamlNode := yaml.Node{}
err := yaml.Unmarshal([]byte(sourceYaml), &yamlNode)
if err != nil {
log.Fatalf("error: %v", err)
}
newApp, err := newApplicationNode("app2", "golang", "app2", "dockerh",
"test", "Second app")
if err != nil {
log.Fatalf("error: %v", err)
}
appIdx := -1
for i, k := range yamlNode.Content[0].Content {
if k.Value == "applications" {
appIdx = i + 1
break
}
}
yamlNode.Content[0].Content[appIdx].Content = append(
yamlNode.Content[0].Content[appIdx].Content, newApp.Content[0])
out, err := yaml.Marshal(&yamlNode)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
}
De toute évidence, au lieu de suivre la voie hacky comme je l'ai fait dans newApplicationNode
, vous pouvez dissocier correctement votre JSON. Cependant, comme indiqué dans les réponses précédentes, il est important de noter que la clé et la valeur réelle se trouvent dans les index suivants à l'intérieur de Content
, vous devez donc en tenir compte lors de la modification du document. (par exemple, recherchez la clé applications
mais considérez ensuite l'index suivant (appIdx = i + 1
dans mon exemple) pour son contenu.
J'espère que cela pourra aider!