Introdução ao JSON em Rust
JSON (JavaScript Object Notation) continua sendo um dos formatos de troca de dados mais populares no desenvolvimento web, arquivos de configuração e APIs. A linguagem Rust, conhecida por seu desempenho e segurança de memória, fornece ferramentas poderosas para trabalhar com JSON através da crate serde_json. Neste artigo, examinaremos minuciosamente como realizar parsing e serialização de JSON em Rust usando abordagens modernas e melhores práticas.
A biblioteca serde (framework de Serialização/Desserialização) é o padrão de fato para trabalhar com formatos de dados no ecossistema Rust. Combinada com serde_json, ela permite converter facilmente estruturas Rust para JSON e vice-versa.
Configuração do Projeto e Instalação de Dependências
Para começar, crie um novo projeto Cargo e adicione as dependências necessárias ao arquivo Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"A flag features = ["derive"] para a crate serde habilita as macros #[derive(Serialize, Deserialize)], que geram automaticamente código para serializar e desserializar estruturas.
Fundamentos do Parsing de JSON em Rust
Convertendo uma String JSON em um Valor Dinâmico
A maneira mais simples de fazer parsing de JSON é usar o tipo serde_json::Value, que representa um valor JSON genérico:
use serde_json::Value;
fn main() { let data = r#" { "name": "Alexey", "age": 30, "is_student": false, "hobbies": ["reading", "programming", "cycling"] }"#;
let parsed: Value = serde_json::from_str(data).expect("Erro no parsing do JSON"); println!("Nome: {}", parsed["name"]); println!("Idade: {}", parsed["age"]); println!("Estudante: {}", parsed["is_student"]); println!("Primeiro hobby: {}", parsed["hobbies"][0]);}O tipo Value é um enum que pode conter Null, Bool, Number, String, Array ou Object. Isso é conveniente para prototipagem rápida, mas para código em produção é melhor usar estruturas fortemente tipadas.
Convertendo JSON em Estruturas Fortemente Tipadas
Para manipulação segura de dados, defina uma estrutura que corresponda ao esquema JSON e use as macros do serde:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]struct Person { name: String, age: u32, is_student: bool, hobbies: Vec<String>,}
fn main() { let json_str = r#" { "name": "Maria", "age": 25, "is_student": true, "hobbies": ["drawing", "music"] }"#;
let person: Person = serde_json::from_str(json_str) .expect("Erro de desserialização"); println!("{:?}", person); println!("{} está estudando: {}", person.name, person.is_student);}A vantagem desta abordagem é que o compilador verifica os tipos em tempo de compilação, eliminando erros em tempo de execução relacionados ao acesso incorreto a campos.
Serializando Dados para JSON
Convertendo Estruturas em uma String JSON
A serialização é realizada usando a função serde_json::to_string():
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct Product { id: u64, name: String, price: f64, in_stock: bool,}
fn main() { let product = Product { id: 42, name: "Laptop".to_string(), price: 89999.99, in_stock: true, };
let json_string = serde_json::to_string(&product) .expect("Erro de serialização"); println!("JSON: {}", json_string); // Pretty print with o