Introdução ao trabalho com JSON em Rust
JSON (JavaScript Object Notation) — um dos formatos mais populares de troca de dados no desenvolvimento web, arquivos de configuração e APIs. Se você está estudando Rust e quer aprender a trabalhar eficientemente com JSON, este artigo é para você. Vamos abordar as principais bibliotecas, princípios de parsing e serialização, além de analisar exemplos práticos de código.
No Rust, o ecossistema para trabalhar com JSON é construído em torno da crate serde — um poderoso framework para serialização e desserialização de dados. Em conjunto com serde_json, ele permite transformar facilmente estruturas de dados em JSON e vice-versa. Vamos entender como isso funciona.
Instalação e configuração de dependências
Para começar, vamos criar um novo projeto e adicionar as dependências necessárias no arquivo Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"A crate serde fornece as macros #[derive(Serialize, Deserialize)], que implementam automaticamente os traits necessários para suas estruturas. serde_json é responsável diretamente pelo trabalho com o formato JSON.
Parsing de JSON: da string para a estrutura
Suponha que temos uma string JSON com informações de um usuário. Queremos transformá-la em uma estrutura tipada do Rust. Veja como fazer:
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]struct User { name: String, age: u32, email: String, is_active: bool,}
fn main() { let json_data = r#" { "name": "Alexey", "age": 28, "email": "alex@example.com", "is_active": true } "#;
// Parsing de JSON para estrutura let user: User = serde_json::from_str(json_data).expect("Erro ao fazer parsing do JSON"); println!("Usuário: {:?}", user); println!("Nome: {}", user.name); println!("Idade: {}", user.age);}Observe o atributo #[derive(Debug, Deserialize, Serialize)]. Debug permite exibir a estrutura no console, enquanto Deserialize e Serialize possibilitam transformar dados em JSON e vice-versa.
Manipulação de objetos aninhados
O JSON frequentemente contém objetos aninhados. Vejamos um exemplo com endereço de usuário:
#[derive(Debug, Deserialize, Serialize)]struct Address { city: String, street: String, zip_code: String,}
#[derive(Debug, Deserialize, Serialize)]struct User { name: String, age: u32, address: Address,}
fn main() { let json_data = r#" { "name": "Maria", "age": 32, "address": { "city": "Moscou", "street": "Tverskaya, 15", "zip_code": "101000" } } "#;
let user: User = serde_json::from_str(json_data).unwrap(); println!("Cidade: {}", user.address.city);}Trabalhando com arrays JSON
Arrays em JSON são transformados em Vec ou outras coleções do Rust:
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Product { id: u32, name: String, price: f64,}
fn main() { let json_array = r#" [ {"id": 1, "name": "Notebook", "price": 75000.50}, {"id": 2, "name": "Mouse", "price": 1500.00}, {"id": 3, "name": "Teclado", "price": 3500.00} ] "#;
let products: Vec<Product> = serde_json::from_str(json_array).unwrap(); for product in &products { println!("{}: {} rub.", product.name, product.price); }}Serialização: da estrutura para JSON
O processo inverso — transformar uma estrutura Rust em uma string JSON. Isso é chamado de s