parser online lib arrays dictionary yaml cross-reference

arrays - online - yaml schema



¿Hay sintaxis YAML para compartir parte de una lista o mapa? (5)

Entonces, sé que puedo hacer algo como esto:

sitelist: &sites - www.foo.com - www.bar.com anotherlist: *sites

Y have sitelist y anotherlist ambos contienen www.foo.com y www.bar.com . Sin embargo, lo que realmente quiero es que otra lista también contenga www.baz.com , sin tener que repetir www.foo.com y www.baz.com .

Hacer esto me da un error de sintaxis en el analizador YAML:

sitelist: &sites - www.foo.com - www.bar.com anotherlist: *sites - www.baz.com

Simplemente usando anclas y alias no parece posible hacer lo que quiero sin agregar otro nivel de subestructura, como:

sitelist: &sites - www.foo.com - www.bar.com anotherlist: - *sites - www.baz.com

Lo que significa que el consumidor de este archivo YAML debe conocerlo.

¿Hay una forma pura de YAML de hacer algo como esto? ¿O tendré que usar algún procesamiento posterior a YAML, como la implementación de la sustitución de variables o el levantamiento automático de ciertos tipos de subestructura? Ya estoy haciendo ese tipo de postprocesamiento para manejar un par de otros casos de uso, así que no soy totalmente contrario a eso. Pero mis archivos YAML serán escritos por humanos, no generados por máquina, así que me gustaría minimizar la cantidad de reglas que los usuarios deben memorizar además de la sintaxis estándar de YAML.

También me gustaría poder hacer lo análogo con los mapas:

namedsites: &sites Foo: www.foo.com Bar: www.bar.com moresites: *sites Baz: www.baz.com

He tenido una búsqueda a través de la especificación YAML , y no he podido encontrar nada, así que sospecho que la respuesta es "no, no puedes hacer esto". Pero si alguien tiene alguna idea, sería genial.

EDITAR: Dado que no ha habido respuestas, supongo que nadie ha detectado nada que no tenga en la especificación YAML y que esto no se puede hacer en la capa YAML. Así que estoy abriendo la pregunta a la idea para el procesamiento posterior de la YAML para ayudar con esto, en caso de que alguien encuentre esta pregunta en el futuro.


(Respondiendo mi propia pregunta en caso de que la solución que estoy usando sea útil para cualquier persona que busque esto en el futuro)

Sin una forma pura de YAML para hacer esto, voy a implementar esto como una "transformación de sintaxis" entre el analizador YAML y el código que realmente usa el archivo de configuración. Por lo tanto, mi aplicación central no tiene que preocuparse en absoluto por ninguna medida de evitación de redundancia amigable con los seres humanos, y solo puede actuar directamente sobre las estructuras resultantes.

La estructura que voy a usar se ve así:

foo: MERGE: - - a - b - c - - 1 - 2 - 3

Que se transformaría en el equivalente de:

foo: - a - b - c - 1 - 2 - 3

O bien, con mapas:

foo: MERGE: - fork: a spoon: b knife: c - cup: 1 mug: 2 glass: 3

Sería transformado a:

foo: fork: a spoon: b knife: c cup: 1 mug: 2 glass: 3

Más formalmente, después de llamar al analizador YAML para obtener objetos nativos de un archivo de configuración, pero antes de pasar los objetos al resto de la aplicación, mi aplicación recorrerá el gráfico de objetos buscando mapeos que contengan la única clave MERGE . El valor asociado con MERGE debe ser una lista de listas o una lista de mapas; cualquier otra subestructura es un error.

En el caso de la lista de listas, todo el mapa que contiene MERGE será reemplazado por las listas secundarias concatenadas en el orden en que aparecieron.

En el caso de la lista de mapas, todo el mapa que contiene MERGE se reemplazará por un solo mapa que contenga todos los pares clave / valor en los mapas secundarios. Cuando hay solapamiento en las teclas, se utilizará el valor del mapa secundario que aparece por última vez en la lista MERGE .

Los ejemplos anteriores no son tan útiles, ya que podría haber escrito la estructura que deseaba directamente. Es más probable que aparezca como:

foo: MERGE: - *salt - *pepper

Permitiéndole crear una lista o un mapa que contenga todo en los nodos de salt y pepper utilizados en otro lugar.

(Sigo dando ese foo: mapa externo para mostrar que MERGE debe ser la única clave en su asignación, lo que significa que MERGE no puede aparecer como un nombre de nivel superior a menos que no haya otros nombres de nivel superior)


Como las respuestas anteriores han señalado, no hay soporte integrado para extender listas en YAML. Te estoy ofreciendo otra forma de implementarlo tú mismo. Considera esto:

defaults: &defaults sites: - www.foo.com - www.bar.com setup1: <<: *defaults sites+: - www.baz.com

Esto se procesará en:

defaults: sites: - www.foo.com - www.bar.com setup1: sites: - www.foo.com - www.bar.com - www.baz.com

La idea es fusionar los contenidos de una tecla que termina con un ''+'' a la tecla correspondiente sin un ''+''. Implementé esto en Python y publiqué here .

¡Disfrutar!


Para aclarar algo de las dos respuestas aquí, esto no se admite directamente en YAML para listas (pero es compatible con diccionarios, consulte la respuesta de kittemon).


Para aprovechar la respuesta de Kittemon, tenga en cuenta que puede crear asignaciones con valores nulos utilizando la sintaxis alternativa

foo: << : myanchor bar: baz:

en lugar de la sintaxis sugerida

foo: << : myanchor ? bar ? baz

Al igual que la sugerencia de Kittemon, esto le permitirá usar referencias a anclas dentro del mapeo y evitar el problema de secuencia. Me di cuenta de que necesitaba hacer esto después de descubrir que el componente Symfony Yaml v2.4.4 no graba el ? bar sintaxis de la ? bar .


El tipo de clave de combinación es probablemente lo que desea. Utiliza una << clave de asignación especial para indicar fusiones, lo que permite utilizar un alias en una asignación (o una secuencia de alias) como inicializador para fusionarse en una sola asignación. Además, aún puede anular valores explícitamente o agregar más que no estaban presentes en la lista de fusión.

Es importante tener en cuenta que funciona con asignaciones, no secuencias como su primer ejemplo. Esto tiene sentido cuando lo piensas, y tu ejemplo parece que probablemente no necesite ser secuencial de todos modos. Simplemente cambiando los valores de su secuencia a las teclas de mapeo debería hacer el truco, como en el siguiente ejemplo (no probado):

sitelist: &sites ? www.foo.com # "www.foo.com" is the key, the value is null ? www.bar.com anotherlist: << : *sites # merge *sites into this mapping ? www.baz.com # add extra stuff

Algunas cosas para notar En primer lugar, como << es una clave, solo se puede especificar una vez por nodo. En segundo lugar, cuando se usa una secuencia como valor, el orden es significativo. Esto no importa en el ejemplo aquí, ya que no hay valores asociados, pero vale la pena ser consciente.