Então, eu sei que posso fazer algo assim:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
E têm sitelist
e anotherlist
ambos contêm www.foo.com
e www.bar.com
. No entanto, o que eu realmente quero é que anotherlist
a também contêm www.baz.com
, sem ter que repetir www.foo.com
e www.baz.com
.
Isso me dá um erro de sintaxe no analisador YAML:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
- www.baz.com
Apenas usando âncoras e aliases, não parece possível fazer o que eu quero sem adicionar outro nível de subestrutura, como:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist:
- *sites
- www.baz.com
O que significa que o consumidor deste arquivo YAML deve estar ciente disso.
Existe uma maneira pura do YAML de fazer algo assim? Ou terei que usar algum processamento pós-YAML, como a implementação da substituição de variável ou levantamento automático de certos tipos de subestrutura? Já estou fazendo esse tipo de pós-processamento para lidar com alguns outros casos de uso, então não sou totalmente avesso a isso. Mas meus arquivos YAML serão escritos por humanos, não gerados por máquina, então eu gostaria de minimizar o número de regras que precisam ser memorizadas por meus usuários em cima da sintaxe YAML padrão.
Eu também gostaria de poder fazer o mesmo com mapas:
namedsites: &sites
Foo: www.foo.com
Bar: www.bar.com
moresites: *sites
Baz: www.baz.com
Fiz uma pesquisa nas especificações YAML e não consegui encontrar nada, então suspeito que a resposta seja apenas "não, você não pode fazer isso". Mas se alguém tiver alguma ideia, isso seria ótimo.
EDIT: Como não houve respostas, estou presumindo que ninguém descobriu nada que eu não tenha na especificação YAML e que isso não pode ser feito na camada YAML. Portanto, estou abrindo a questão para a ideia de pós-processamento do YAML para ajudar com isso, caso alguém encontre essa questão no futuro.
Respostas:
O tipo de chave de mesclagem é provavelmente o que você deseja. Ele usa uma
<<
chave de mapeamento especial para indicar mesclagens, permitindo que um alias para um mapeamento (ou uma sequência de tais aliases) seja usado como um inicializador para mesclar em um único mapeamento. Além disso, você ainda pode substituir valores explicitamente ou adicionar mais que não estavam presentes na lista de mesclagem.É importante observar que ele funciona com mapeamentos, não com sequências como seu primeiro exemplo. Isso faz sentido quando você pensa sobre isso e seu exemplo parece que provavelmente não precisa ser sequencial de qualquer maneira. Basta alterar seus valores de sequência para as chaves de mapeamento, como no exemplo a seguir (não testado):
Algumas coisas a serem observadas. Em primeiro lugar, como
<<
é uma chave, ela só pode ser especificada uma vez por nó. Em segundo lugar, ao usar uma sequência como valor, a ordem é significativa. Isso não importa no exemplo aqui, pois não existem valores associados, mas vale a pena estar atento.fonte
yaml.load(...)
em Python, recebo um dicionário como a representação de um mapeamento YAML. Sim, é fácil pós-processar isso em um conjunto, mas preciso saber o que aconteceu (e a complexidade semântica ao ler / gravar os arquivos de configuração é muito maior se a regra for "conjuntos são escritos como mapas com valores nulos" ) Dado que preciso de um pós-processamento entreyaml.load(...)
e usando os dados resultantes, quer eu use<<
ouMERGE
, provavelmente irei continuarMERGE
(que já implementei agora).!!set
funciona. Muito boilerplate obscuro embora. Esses arquivos são feitos para serem lidos / gravados por humanos, por pessoas que não são necessariamente especialistas em YAML. As pessoas vão escrever suas listas de sites como listas YAML, em seguida, querem mesclá-los e ter que converter tudo para um conjunto E lembre-se de marcá-lo explicitamente como um conjunto ... Eu tenho alguns outros post- padronizados processar coisas junto com deMERGE
qualquer maneira. Obrigado pela sua ajuda!Como as respostas anteriores indicaram, não há suporte integrado para estender listas em YAML. Estou oferecendo mais uma maneira de implementá-lo sozinho. Considere isto:
Isso será processado em:
A ideia é mesclar o conteúdo de uma tecla que termina com um '+' à tecla correspondente sem um '+'. Implementei isso em Python e publiquei aqui .
Aproveitar!
fonte
sites
esites+
. Quero dizer uma ferramenta que deve ser implementada pelo usuário, pois este não é umyaml
comportamento padrão ?(Respondendo minha própria pergunta caso a solução que estou usando seja útil para alguém que pesquisar por isso no futuro)
Sem uma maneira pura de YAML de fazer isso, vou implementar isso como uma "transformação de sintaxe" situada entre o analisador YAML e o código que realmente usa o arquivo de configuração. Portanto, meu aplicativo principal não precisa se preocupar com nenhuma medida de prevenção de redundância amigável e pode apenas agir diretamente nas estruturas resultantes.
A estrutura que vou usar é assim:
Que seria transformado no equivalente a:
Ou, com mapas:
Seria transformado em:
Mais formalmente, depois de chamar o analisador YAML para obter objetos nativos de um arquivo de configuração, mas antes de passar os objetos para o resto do aplicativo, meu aplicativo percorrerá o gráfico de objetos procurando mapeamentos contendo a chave única
MERGE
. O valor associadoMERGE
deve ser uma lista de listas ou uma lista de mapas; qualquer outra subestrutura é um erro.No caso de lista de listas, todo o mapa que contém
MERGE
será substituído pelas listas secundárias concatenadas na ordem em que apareceram.No caso da lista de mapas, todo o mapa contendo
MERGE
será substituído por um único mapa contendo todos os pares chave / valor nos mapas filho. Onde houver sobreposição nas chaves, o valor do mapa filho que ocorre por último naMERGE
lista será usado.Os exemplos dados acima não são tão úteis, já que você poderia apenas ter escrito a estrutura desejada diretamente. É mais provável que apareça como:
Permitindo que você crie uma lista ou mapa contendo tudo em nós
salt
epepper
sendo usado em outro lugar.(Eu continuo fornecendo aquele
foo:
mapa externo para mostrar queMERGE
deve ser a única chave em seu mapeamento, o que significa queMERGE
não pode aparecer como um nome de nível superior a menos que não haja outros nomes de nível superior)fonte
Para esclarecer algo sobre as duas respostas aqui, isso não é suportado diretamente no YAML para listas (mas é compatível com dicionários, consulte a resposta do kittemon).
fonte
Para pegar carona na resposta de Kittemon, observe que você pode criar mapeamentos com valores nulos usando a sintaxe alternativa
em vez da sintaxe sugerida
Como a sugestão de Kittemon, isso permitirá que você use referências a âncoras no mapeamento e evite o problema de sequência. Descobri que precisava fazer isso depois de descobrir que o componente Symfony Yaml v2.4.4 não reconhece a
? bar
sintaxe.fonte
myanchor
parece?