Introdução
Yaml é uma das linguagens de serialização de dados mais populares depois JSON. Portanto, às vezes é chamado de rigoroso superconjunto de JSON. Ele foi projetado para interação humana e legibilidade desde o início, portanto, é conhecido por sua simplicidade. Ele foi projetado com flexibilidade e acessibilidade em mente, por isso funciona com todas as linguagens de programação modernas e um formato poderoso para gravar arquivos de configuração. Também é usado para persistência de dados, mensagens na Internet, compartilhamento de dados entre idiomas e muitas outras opções.
O YAML foi iniciado em 2001 e foi denominado como “Mais uma linguagem de marcação" naquela hora. Mas depois foi registrado como “YAML não é linguagem de marcação“. A estrutura básica de um arquivo YAML é uma mapa,. Também é conhecido como dicionário, hash(mapa) ou simplesmente baseado em objetos na linguagem de programação que optamos por usar.
Espaço em branco e recuo são usados em arquivos YAML para denotar aninhamento.
Note: Somente espaços podem ser usados para recuo em arquivos YAML; caracteres de tabulação não são permitidos. Desde que o recuo seja feito de forma consistente, não importa quantos espaços sejam utilizados.
Sintaxe YAML
Um formato YAML usa principalmente 3 tipos de nós:
- Mapas/Dicionários: UMA mapa, o conteúdo do nó é uma coleção não ordenada de valor chave nó pares, com o requisito de que cada chave deve ser distinta. Nenhuma outra limitação é imposta aos nós pelo YAML.
- Matrizes/Listas: A ordem o conteúdo do nó é uma coleção ordenada de zero ou mais nós. Uma sequência pode incluir o mesmo nó mais de uma vez, em particular. Pode conter até a si mesmo.
- Literais (Strings, números, boolean, etc.): Uma sequência de zero ou mais Caracteres Unicode pode ser usado para representar os dados opacos que compõem um escalar conteúdo do nó.
Neste artigo, analisaremos especificamente a conversão de conteúdo de matriz YAML em uma lista em Java. Existem muitas bibliotecas de código aberto disponíveis, mas as mais populares delas são Jackson e CobraYAML. Neste guia, usaremos SnakeYaml como nossa biblioteca para analisar o conteúdo YAML.
SnakeYamlGenericName
CobraYAML é um pacote de análise YAML que oferece uma API de alto nível para serialização e desserialização de documentos YAML. O ponto de entrada para SnakeYAML é o Yaml
classe. Os documentos ou os arquivos YAML podem ser carregados usando load()
método ou em lote através do loadAll()
método. Os métodos pegam dados YAML genuínos na forma de objetos String, bem como InputStreams
, que é um tipo de arquivo típico para encontrar.
Considerando a :
estrutura inata para arquivos YAML, SnakeYAML naturalmente funciona bem com Mapas Java, mas também podemos usar objetos Java.
Para incluir a biblioteca em nosso projeto, adicione a seguinte dependência ao seu pom.xml
arquivo:
<dependencies>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
</dependencies>
Ou, se você estiver usando o Gradle:
compile group: 'org.yaml', name: 'snakeyaml', version: '1.33'
Lendo uma matriz YAML simples
Vamos começar rapidamente lendo uma matriz simples de um arquivo YAML. Considere que temos um arquivo yaml com os seguintes dados na pasta de recursos do nosso projeto Java:
- One
- Two
- Three
- Four
Então podemos carregar o conteúdo do arquivo como um InputStream
. A seguir, vamos construir o Yaml
instância que atuará como um ponto de entrada para acessar a biblioteca e o objeto para representar o conteúdo do arquivo YAML programaticamente. o load()
método nos permite ler e analisar qualquer InputStream
com dados YAML válidos:
public void readYamlWithArray() {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("number.yml");
Yaml yaml = new Yaml();
List data = yaml.load(inputStream);
System.out.println(data);
}
O método retornará um Java List
de dados String. Se imprimirmos o data
então dará o seguinte resultado:
[One, Two, Three, Four]
Lendo uma matriz agrupada YAML
Às vezes, gostaríamos de definir uma matriz de conteúdo em relação a uma determinada chave. Isso é chamado de agrupamento de matrizes em um nó de mapa YAML. Um exemplo de YAML desse tipo se parece com o seguinte:
languages:
- Java
- JavaScript
- Python
- Golang
- Perl
- Shell
- Scala
Isso pode ser considerado como Java Map
contendo um :
onde o valor é um ordem. Assim, os dados ainda serão carregados como InputStream
como definimos acima. Mas o data
deve ser definido como Map
of List
of String
s:
public void readYamlWithArrayGroup() {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("language.yml");
Yaml yaml = new Yaml();
Map<String, List> data = yaml.load(inputStream);
System.out.println(data);
data.values()
.stream()
.collect(Collectors.toList())
.get(0)
.forEach(System.out::println);
}
Agora, se lermos nosso data
, seria mais ou menos assim:
{languages=[Java, JavaScript, Python, Golang, Perl, Shell, Scala]}
Java
JavaScript
Python
Golang
Perl
Shell
Scala
Lendo uma matriz de várias linhas YAML de matrizes
Às vezes nos deparamos com um arquivo YAML com dados contendo array de arrays. Por exemplo, agrupamos os cursos e os representamos como array de arrays como abaixo:
courses:
- - C
- Java
- Data Structures
- Algorithms
- - Big Data
- Spark
- Kafka
- Machine Learning
Isso pode ser analisado como Java Map
of List
of List
of String
. Podemos carregar novamente o InputStream
como fizemos anteriormente. Mas os dados serão carregados conforme abaixo:
Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!
public void readYamlWithMultiLineArrayGroup() {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("courses.yml");
Yaml yaml = new Yaml();
Map<String, List<List>> data = yaml.load(inputStream);
System.out.println(data);
System.out.println("First Array Group:");
data.values()
.stream()
.collect(Collectors.toList())
.get(0)
.get(0)
.forEach(System.out::println);
System.out.println("nSecond Array Group:");
data.values()
.stream()
.collect(Collectors.toList())
.get(0)
.get(1)
.forEach(System.out::println);
}
Então, se imprimirmos o data
, ficaria algo como abaixo:
{courses=[[C, Java, Data Structures, Algorithms], [Big Data, Spark, Kafka, Machine Learning]]}
First Array Group:
C
Java
Data Structures
Algorithms
Second Array Group:
Big Data
Spark
Kafka
Machine Learning
Lendo um conteúdo YAML aninhado complexo como Java Bean
Vimos como podemos lidar com o conteúdo do tipo array separadamente, mas com arquivos YAML aninhados complexos – ter um mapa de mapas com listas de listas é difícil de analisar intuitivamente e difícil de lidar. Mesmo no último exemplo, onde tínhamos apenas duas listas aninhadas – lidar com elas como listas fica bastante detalhado.
Nesses casos, é melhor criar um POJO que possa ser mapeado para os dados YAML aninhados. Vamos primeiro criar um YAML de amostra contendo o conteúdo aninhado de um site:
website: stackabuse
skills:
- python
- javascript
- java
- unix
- machine learning
- web development
tutorials:
- graphs:
name: Graphs in Python - Theory and Implementation
tags:
- python
- data structures
- algorithm
contributors:
- David Landup
- Dimitrije Stamenic
- Jovana Ninkovic
last_updated: June 2022
- git:
name: Git Essentials - Developer's Guide to Git
tags:
- git
contributors:
- David Landup
- François Dupire
- Jovana Ninkovic
last_updated: April 2022
- deep learning:
name: Practical Deep Learning for Computer Vision with Python
tags:
- python
- machine learning
- tensorflow
- computer vision
contributors:
- David Landup
- Jovana Ninkovic
last_updated: October 2022
published: true
Precisamos definir uma classe Java pai WebsiteContent
que consistirá em List
de habilidades e um List
of Map
de tutoriais que novamente conterão listas de tags e contribuidores:
public class WebsiteContent {
private String website;
private List skills;
private List<Map> tutorials;
private Boolean published;
@Override
public String toString() {
return "WebsiteContent{" +
"website='" + website + ''' +
", skills=" + skills +
", tutorials=" + tutorials +
", published=" + published +
'}';
}
}
public class Tutorial {
private String name;
private List tags;
private List contributors;
private String lastUpdated;
@Override
public String toString() {
return "Tutorial{" +
"name='" + name + ''' +
", tags=" + tags +
", contributors=" + contributors +
", lastUpdated='" + lastUpdated + ''' +
'}';
}
}
Agora podemos carregar novamente os dados do arquivo como InputStream
como fizemos anteriormente. Em seguida, quando criamos nosso Yaml
objeto de classe, precisamos especificar o tipo de dados em que queremos converter os dados. o new Constructor(WebsiteContent.class)
diz ao SnakeYAML para ler os dados do arquivo YAML mapeá-lo para o nosso WebsiteContent
objeto.
O mapeamento é direto e os nomes de nossos atributos de objeto devem corresponder aos nomes dos atributos YAML.
public void readYamlAsBeanWithNestedArrays(){
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("website_content.yml");
Yaml yaml = new Yaml(new Constructor(WebsiteContent.class));
WebsiteContent data = yaml.load(inputStream);
System.out.println(data);
System.out.println("nList of Skills: ");
data.getSkills().stream().forEach(System.out::println);
System.out.println("nList of Tutorials: ");
data.getTutorials().stream().forEach(System.out::println);
}
Por fim, quando imprimimos o data
, ficaria algo como abaixo:
WebsiteContent{website='stackabuse', skills=[python, javascript, java, unix, machine learning, web development], tutorials=[{graphs={name=Graphs in Python - Theory and Implementation, tags=[python, data structures, algorithm], contributors=[David Landup, Dimitrije Stamenic, Jovana Ninkovic], last_updated=June 2022}}, {git={name=Git Essentials - Developer's Guide to Git, tags=[git], contributors=[David Landup, François Dupire, Jovana Ninkovic], last_updated=April 2022}}, {deep learning={name=Practical Deep Learning for Computer Vision with Python, tags=[python, machine learning, tensorflow, computer vision], contributors=[David Landup, Jovana Ninkovic], last_updated=October 2022}}], published=true}
List of Skills:
python
javascript
java
unix
machine learning
web development
List of Tutorials:
{graphs={name=Graphs in Python - Theory and Implementation, tags=[python, data structures, algorithm], contributors=[David Landup, Dimitrije Stamenic, Jovana Ninkovic], last_updated=June 2022}}
{git={name=Git Essentials - Developer's Guide to Git, tags=[git], contributors=[David Landup, François Dupire, Jovana Ninkovic], last_updated=April 2022}}
{deep learning={name=Practical Deep Learning for Computer Vision with Python, tags=[python, machine learning, tensorflow, computer vision], contributors=[David Landup, Jovana Ninkovic], last_updated=October 2022}}
Como podemos ver, o SnakeYaml analisou e converteu com sucesso o WebsiteContent
objeto e manteve a herança e associação com Tutorial
objeto intacto.
Conclusão
Como os arquivos YAML são amplamente usados para DevOps e dados relacionados à configuração, é bastante útil analisar e manipular os dados usando código.
SnakeYAML nos permite gerenciar arquivos YAML em nosso projeto Java com facilidade, e requer apenas um pouco de código para carregar arquivos YAML em nosso projeto ou gravar dados em arquivos YAML. Além disso, o SnakeYAML oferece opções de formatação para que você possa ajustá-lo e personalizá-lo para atender às nossas necessidades.