Donc, je sais que je peux faire quelque chose comme ça:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
Et ont sitelist
et anotherlist
contiennent tous les deux www.foo.com
et www.bar.com
. Cependant, ce que je veux vraiment est pour anotherlist
à également contenir www.baz.com
, sans avoir à répéter www.foo.com
etwww.baz.com
.
Cela me donne une erreur de syntaxe dans l'analyseur YAML:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
- www.baz.com
En utilisant simplement des ancres et des alias, il ne semble pas possible de faire ce que je veux sans ajouter un autre niveau de sous-structure, tel que:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist:
- *sites
- www.baz.com
Ce qui signifie que le consommateur de ce fichier YAML doit en être conscient.
Existe-t-il une manière pure YAML de faire quelque chose comme ça? Ou vais-je devoir utiliser un traitement post-YAML, comme l'implémentation de la substitution de variables ou la levée automatique de certains types de sous-structures? Je fais déjà ce genre de post-traitement pour gérer quelques autres cas d'utilisation, donc je ne suis pas totalement opposé à cela. Mais mes fichiers YAML vont être écrits par des humains, pas générés par la machine, donc je voudrais minimiser le nombre de règles qui doivent être mémorisées par mes utilisateurs en plus de la syntaxe YAML standard.
J'aimerais aussi pouvoir faire la chose analogue avec les cartes:
namedsites: &sites
Foo: www.foo.com
Bar: www.bar.com
moresites: *sites
Baz: www.baz.com
J'ai fait une recherche dans la spécification YAML et je n'ai rien trouvé, donc je soupçonne que la réponse est simplement "non, vous ne pouvez pas faire ça". Mais si quelqu'un a des idées, ce serait génial.
EDIT: Puisqu'il n'y a eu aucune réponse, je suppose que personne n'a repéré quoi que ce soit que je n'ai pas dans la spécification YAML et que cela ne peut pas être fait au niveau de la couche YAML. J'ouvre donc la question à l'idée de post-traitement du YAML pour aider avec cela, au cas où quelqu'un trouverait cette question à l'avenir.
Réponses:
Le type de clé de fusion est probablement ce que vous voulez. Il utilise un spécial
<<
clé de mappage pour indiquer les fusions, permettant à un alias d'un mappage (ou d'une séquence de tels alias) d'être utilisé comme initialiseur pour fusionner en un seul mappage. En outre, vous pouvez toujours remplacer explicitement les valeurs ou en ajouter d'autres qui n'étaient pas présentes dans la liste de fusion.Il est important de noter que cela fonctionne avec des mappages, pas des séquences comme premier exemple. Cela a du sens quand vous y réfléchissez, et votre exemple semble ne pas avoir besoin d'être séquentiel de toute façon. Changer simplement vos valeurs de séquence en clés de mappage devrait faire l'affaire, comme dans l'exemple suivant (non testé):
Quelques choses à remarquer. Premièrement, puisqu'il
<<
s'agit d'une clé, elle ne peut être spécifiée qu'une seule fois par nœud. Deuxièmement, lorsque vous utilisez une séquence comme valeur, l'ordre est significatif. Cela n'a pas d'importance dans l'exemple ici, car il n'y a pas de valeurs associées, mais cela vaut la peine d'être conscient.la source
yaml.load(...)
en Python, j'obtiens un dictionnaire comme représentation d'un mappage YAML. Oui, il est facile de post-traiter cela dans un ensemble, mais je dois savoir que cela s'est produit (et la complexité sémantique lors de la lecture / écriture des fichiers de configuration est beaucoup plus élevée si la règle est "les ensembles sont écrits comme des cartes avec des valeurs nulles" ). Étant donné que j'ai besoin d'un post-traitement entreyaml.load(...)
et en utilisant les données résultantes, que j'utilise<<
ouMERGE
, je m'en tiendrai probablementMERGE
(ce que j'ai déjà implémenté maintenant).!!set
marche. Trop de passe-partout obscur cependant. Ces fichiers sont conçus pour être lisibles / inscriptibles par l'homme, par des personnes qui ne sont pas nécessairement des experts YAML. Les gens vont écrire leurs listes de sites sous forme de listes YAML, puis veulent les fusionner et doivent convertir le tout en un ensemble ET n'oubliez pas de le marquer explicitement comme un ensemble ... J'ai quelques autres articles standardisés. traitement des choses avec deMERGE
toute façon. Merci quand même pour vôtre aide!Comme les réponses précédentes l'ont souligné, il n'y a pas de support intégré pour l'extension des listes dans YAML. Je propose encore une autre façon de le mettre en œuvre vous-même. Considère ceci:
Cela sera traité en:
L'idée est de fusionner le contenu d'une clé se terminant par un '+' à la clé correspondante sans un '+'. J'ai implémenté cela en Python et publié ici .
Prendre plaisir!
la source
sites
etsites+
. Je veux dire un outil qui doit être implémenté par l'utilisateur car ce n'est pas unyaml
comportement par défaut ?(Répondre à ma propre question au cas où la solution que j'utilise serait utile à quiconque la recherche à l'avenir)
En l'absence de moyen purement YAML de le faire, je vais implémenter cela comme une «transformation de syntaxe» entre l'analyseur YAML et le code qui utilise réellement le fichier de configuration. Ainsi, mon application principale n'a pas du tout à se soucier des mesures d'évitement de redondance conviviales pour l'homme, et peut simplement agir directement sur les structures résultantes.
La structure que je vais utiliser ressemble à ceci:
Ce qui serait transformé en l'équivalent de:
Ou, avec des cartes:
Serait transformé en:
Plus formellement, après avoir appelé l'analyseur YAML pour obtenir des objets natifs à partir d'un fichier de configuration, mais avant de passer les objets au reste de l'application, mon application parcourra le graphe d'objets à la recherche de mappages contenant la clé unique
MERGE
. La valeur associée àMERGE
doit être soit une liste de listes, soit une liste de cartes; toute autre sous-structure est une erreur.Dans le cas des listes de listes, la carte entière contenant
MERGE
sera remplacée par les listes enfants concaténées ensemble dans l'ordre d'apparition.Dans le cas de la liste de mappes, la mappe entière contenant
MERGE
sera remplacée par une mappe unique contenant toutes les paires clé / valeur des mappes enfants. En cas de chevauchement des clés, la valeur de la carte enfant apparaissant en dernierMERGE
liste sera utilisée.Les exemples donnés ci-dessus ne sont pas très utiles, car vous auriez pu simplement écrire la structure que vous vouliez directement. Il est plus susceptible d'apparaître comme:
Vous permettant de créer une liste ou une carte contenant tout ce qui se trouve dans les nœuds
salt
etpepper
utilisée ailleurs.(Je continue de donner cette
foo:
carte externe pour montrer queMERGE
doit être la seule clé de son mappage, ce qui signifie queMERGE
cela ne peut pas apparaître comme un nom de niveau supérieur à moins qu'il n'y ait pas d'autres noms de niveau supérieur)la source
Pour clarifier quelque chose à partir des deux réponses ici, cela n'est pas pris en charge directement dans YAML pour les listes (mais il est pris en charge pour les dictionnaires, voir la réponse de kittemon).
la source
Pour utiliser la réponse de Kittemon, notez que vous pouvez créer des mappages avec des valeurs nulles en utilisant la syntaxe alternative
au lieu de la syntaxe suggérée
Comme la suggestion de Kittemon, cela vous permettra d'utiliser des références aux ancres dans le mappage et d'éviter le problème de séquence. Je me suis retrouvé à devoir le faire après avoir découvert que le composant Symfony Yaml v2.4.4 ne reconnaissait pas la
? bar
syntaxe.la source
myanchor
ressemble?