Introdução: por que JSON é importante em Rust?
JSON (JavaScript Object Notation) continua sendo um dos formatos mais populares para troca de dados entre serviços, arquivos de configuração e APIs. No ecossistema Rust, o trabalho com JSON é implementado através do poderoso crate serde_json, que, em conjunto com o framework serde, oferece uma maneira elegante e segura de transformar estruturas de dados.
Ao contrário das linguagens dinâmicas, Rust exige a descrição explícita dos tipos, o que pode parecer complicado à primeira vista. No entanto, na prática, isso proporciona uma confiabilidade incrível: você nunca receberá um null inesperado ou um campo com tipo incorreto durante a execução. Neste artigo, abordaremos o parsing (desserialização) e a serialização de JSON com exemplos concretos que podem ser aplicados imediatamente em projetos reais.
1. Configuração do projeto e instalação de dependências
Antes de escrever código, vamos adicionar os crates necessários no Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"O crate serde com a flag derive permite gerar automaticamente o código para serialização e desserialização das nossas estruturas. O serde_json é responsável diretamente pela conversão de/para JSON.
Importamos tudo o que é necessário no main.rs:
use serde::{Deserialize, Serialize};use serde_json::Result;2. Serialização: transformando uma estrutura Rust em JSON
Serialização é o processo de converter um objeto Rust em uma string JSON. Vamos considerar um exemplo clássico com dados de usuário.
Declaração da estrutura
Adicionamos as anotações #[derive(Serialize, Deserialize)] à nossa estrutura:
#[derive(Debug, Serialize, Deserialize)]struct User { id: u32, name: String, email: String, is_active: bool, tags: Vec<String>,}Criação da instância e serialização
Agora criamos um objeto e o convertemos para JSON:
fn main() -> Result<()> { let user = User { id: 42, name: "Alexei".to_string(), email: "alex@example.com".to_string(), is_active: true, tags: vec!["rust".to_string(), "backend".to_string()], };
// Serialização para string JSON let json_string = serde_json::to_string(&user)?; println!("{}", json_string);
// Serialização bonita (pretty) let pretty_json = serde_json::to_string_pretty(&user)?; println!("{}", pretty_json);
Ok(())}Resultado da execução:
{"id":42,"name":"Alexei","email":"alex@example.com","is_active":true,"tags":["rust","backend"]}
{ "id": 42, "name": "Alexei", "email": "alex@example.com", "is_active": true, "tags": [ "rust", "backend" ]}Observe: to_string_pretty adiciona indentação e quebras de linha — ideal para arquivos de configuração ou logs.
3. Parsing (desserialização): de JSON para estrutura Rust
Desserialização é o processo inverso: recebemos uma string JSON e a convertemos em uma estrutura tipada do Rust.
Parsing a partir de uma string
fn parse_user_from_json(json_str: &str) -> Result<User> { let user: User = serde_json::from_str(json_str)?; Ok(user)}
fn main() -> Result<()> { let data = r#" { "id": 101, "name": "Maria", "email": "maria@example.com", "is_active": false, "tags": ["python", "data-science"] } "#;
let user = parse_user_from_json(data)?; println!("Usuário: {:?}", user); println!("Nome: {}", user.name); println!("Ativo: {}", user.is_active);
Ok(())}Se o JSON não corresponder à estrutura (ex