Web Rust 数据序列化示例
Web Rust 数据序列化示例,包括JSON序列化、反序列化和XML解析
💻 JSON序列化 rust
🟢 simple
⭐⭐
使用serde_json将Rust对象序列化为JSON字符串
⏱️ 20 min
🏷️ rust, web, serialization, json
Prerequisites:
Basic Rust, serde, serde_json
// Web Rust JSON Serialization Examples
// Serialize Rust objects to JSON
//
// Add to Cargo.toml:
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
use serde::{Deserialize, Serialize, Serializer};
use serde_json::{json, to_string_pretty, Value};
// 1. Basic Serialization
/// Person struct with Serialize derive
#[derive(Debug, Serialize)]
struct Person {
name: String,
age: u32,
email: String,
active: bool,
}
/// Serialize struct to JSON string
fn serialize_to_json<T: Serialize>(value: &T) -> Result<String, serde_json::Error> {
serde_json::to_string(value)
}
/// Serialize struct to pretty JSON string
fn serialize_to_pretty_json<T: Serialize>(value: &T) -> Result<String, serde_json::Error> {
to_string_pretty(value)
}
// 2. Serialize Collections
/// Serialize vector to JSON array
fn serialize_vector(items: &[i32]) -> Result<String, serde_json::Error> {
serde_json::to_string(items)
}
/// Serialize HashMap to JSON object
fn serialize_map(map: &std::collections::HashMap<String, String>) -> Result<String, serde_json::Error> {
serde_json::to_string(map)
}
/// Serialize vector of structs
fn serialize_persons(persons: &[Person]) -> Result<String, serde_json::Error> {
serde_json::to_string(persons)
}
// 3. Custom Serialization
/// Serialize with custom field names
#[derive(Debug, Serialize)]
struct User {
#[serde(rename = "userId")]
id: u32,
#[serde(rename = "userName")]
name: String,
#[serde(rename = "userEmail")]
email: String,
}
/// Serialize with conditionally skipped fields
#[derive(Debug, Serialize)]
struct Product {
id: u32,
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
tags: Vec<String>,
#[serde(skip_serializing)]
internal_id: String,
}
// 4. Serialize Enums
/// Serialize simple enum
#[derive(Debug, Serialize)]
enum Status {
Active,
Inactive,
Pending,
}
/// Serialize enum with data
#[derive(Debug, Serialize)]
enum Message {
Text(String),
Image { url: String, size: u32 },
Video { url: String, duration: u32 },
}
/// Serialize enum with associated values
#[derive(Debug, Serialize)]
enum Response {
Success(String),
Error { code: u32, message: String },
Empty,
}
// 5. Serialize with Custom Formatting
/// Serialize date as custom format
#[derive(Debug, Serialize)]
struct Event {
name: String,
#[serde(serialize_with = "serialize_date")]
date: chrono::NaiveDate,
}
fn serialize_date<S>(date: &chrono::NaiveDate, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let formatted = date.format("%Y-%m-%d").to_string();
serializer.serialize_str(&formatted)
}
// 6. Serialize to Value
/// Serialize to generic JSON Value
fn serialize_to_value<T: Serialize>(value: &T) -> Result<Value, serde_json::Error> {
serde_json::to_value(value)
}
/// Build JSON object dynamically
fn build_json_object(name: &str, age: u32, email: &str) -> Value {
json!({
"name": name,
"age": age,
"email": email,
"created_at": "2024-01-15"
})
}
/// Build JSON array dynamically
fn build_json_array(items: &[&str]) -> Value {
json!(items)
}
// 7. Serialize with Transformation
/// Serialize with computed field
#[derive(Debug, Serialize)]
struct Invoice {
items: Vec<InvoiceItem>,
#[serde(skip_serializing)]
tax_rate: f64,
#[serde(serialize_with = "serialize_total")]
total: f64,
}
#[derive(Debug, Serialize)]
struct InvoiceItem {
name: String,
quantity: u32,
price: f64,
}
fn serialize_total<S>(total: &f64, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let formatted = format!("{:.2}", total);
serializer.serialize_str(&formatted)
}
// 8. Serialize Nested Structures
/// Serialize nested objects
#[derive(Debug, Serialize)]
struct Company {
name: String,
address: Address,
employees: Vec<Employee>,
}
#[derive(Debug, Serialize)]
struct Address {
street: String,
city: String,
country: String,
postal_code: String,
}
#[derive(Debug, Serialize)]
struct Employee {
id: u32,
name: String,
position: String,
department: String,
}
// 9. Serialize Optional and Null
/// Serialize optional fields
#[derive(Debug, Serialize)]
struct Profile {
username: String,
#[serde(skip_serializing_if = "Option::is_none")]
bio: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
avatar_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
website: Option<String>,
}
// 10. Serialize with Custom Wrapper
/// Serialize with wrapper object
#[derive(Debug, Serialize)]
struct ApiResponse<T> {
success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
message: Option<String>,
data: T,
}
/// Create API response wrapper
fn create_response<T: Serialize>(data: T, message: Option<String>) -> ApiResponse<T> {
ApiResponse {
success: true,
message,
data,
}
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust JSON Serialization Examples ===\n");
// 1. Basic serialization
println!("--- 1. Basic Serialization ---");
let person = Person {
name: "Alice".to_string(),
age: 30,
email: "[email protected]".to_string(),
active: true,
};
println!("Serialized: {}", serialize_to_json(&person)?);
println!("Pretty:\n{}", serialize_to_pretty_json(&person)?);
// 2. Serialize collections
println!("\n--- 2. Serialize Collections ---");
let numbers = vec![1, 2, 3, 4, 5];
println!("Vector: {}", serialize_vector(&numbers)?);
let mut map = std::collections::HashMap::new();
map.insert("key1".to_string(), "value1".to_string());
map.insert("key2".to_string(), "value2".to_string());
println!("Map: {}", serialize_map(&map)?);
// 3. Custom field names
println!("\n--- 3. Custom Field Names ---");
let user = User {
id: 1,
name: "Bob".to_string(),
email: "[email protected]".to_string(),
};
println!("User: {}", serialize_to_pretty_json(&user)?);
// 4. Conditional serialization
println!("\n--- 4. Conditional Serialization ---");
let product = Product {
id: 1,
name: "Laptop".to_string(),
description: Some("High-performance laptop".to_string()),
tags: vec!["electronics".to_string(), "computers".to_string()],
internal_id: "INT-123".to_string(),
};
println!("Product: {}", serialize_to_pretty_json(&product)?);
// 5. Serialize enums
println!("\n--- 5. Serialize Enums ---");
let status = Status::Active;
println!("Status: {}", serialize_to_json(&status)?);
let message = Message::Image {
url: "https://example.com/image.jpg".to_string(),
size: 1024,
};
println!("Message: {}", serialize_to_json(&message)?);
// 6. Dynamic JSON
println!("\n--- 6. Dynamic JSON ---");
let obj = build_json_object("Charlie", 25, "[email protected]");
println!("Dynamic object: {}", to_string_pretty(&obj)?);
let arr = build_json_array(&["apple", "banana", "orange"]);
println!("Dynamic array: {}", to_string_pretty(&arr)?);
// 7. Nested structures
println!("\n--- 7. Nested Structures ---");
let company = Company {
name: "Tech Corp".to_string(),
address: Address {
street: "123 Main St".to_string(),
city: "San Francisco".to_string(),
country: "USA".to_string(),
postal_code: "94102".to_string(),
},
employees: vec![
Employee {
id: 1,
name: "Alice".to_string(),
position: "Developer".to_string(),
department: "Engineering".to_string(),
},
],
};
println!("Company: {}", serialize_to_pretty_json(&company)?);
// 8. Optional fields
println!("\n--- 8. Optional Fields ---");
let profile = Profile {
username: "alice".to_string(),
bio: Some("Software developer".to_string()),
avatar_url: None,
website: Some("https://alice.dev".to_string()),
};
println!("Profile: {}", serialize_to_pretty_json(&profile)?);
// 9. API response wrapper
println!("\n--- 9. API Response Wrapper ---");
let response = create_response(
person,
Some("User retrieved successfully".to_string()),
);
println!("API Response: {}", serialize_to_pretty_json(&response)?);
// 10. Custom transformation
println!("\n--- 10. Custom Transformation ---");
let invoice = Invoice {
items: vec![
InvoiceItem {
name: "Service A".to_string(),
quantity: 2,
price: 100.0,
},
],
tax_rate: 0.1,
total: 220.0,
};
println!("Invoice: {}", serialize_to_pretty_json(&invoice)?);
println!("\n=== All JSON Serialization Examples Completed ===");
Ok(())
}
💻 JSON反序列化 rust
🟡 intermediate
⭐⭐⭐
将JSON字符串反序列化为Rust对象并处理错误
⏱️ 20 min
🏷️ rust, web, serialization, json
Prerequisites:
Intermediate Rust, serde, serde_json
// Web Rust JSON Deserialization Examples
// Deserialize JSON strings to Rust objects
//
// Add to Cargo.toml:
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
use serde::{Deserialize, Serialize, Deserializer};
use serde_json::{from_str, Value};
use std::collections::HashMap;
// 1. Basic Deserialization
/// Person struct with Deserialize derive
#[derive(Debug, Deserialize, Serialize)]
struct Person {
name: String,
age: u32,
email: String,
active: bool,
}
/// Deserialize JSON string to struct
fn deserialize_from_json<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T, serde_json::Error> {
from_str(json)
}
// 2. Deserialize Collections
/// Deserialize JSON array to vector
fn deserialize_to_vector(json: &str) -> Result<Vec<i32>, serde_json::Error> {
from_str(json)
}
/// Deserialize JSON object to HashMap
fn deserialize_to_map(json: &str) -> Result<HashMap<String, String>, serde_json::Error> {
from_str(json)
}
/// Deserialize JSON array of objects
fn deserialize_to_persons(json: &str) -> Result<Vec<Person>, serde_json::Error> {
from_str(json)
}
// 3. Flexible Deserialization
/// Deserialize struct with optional fields
#[derive(Debug, Deserialize)]
struct UserProfile {
username: String,
#[serde(default)]
bio: String,
#[serde(default)]
avatar_url: Option<String>,
#[serde(default)]
active: bool,
}
/// Deserialize struct with default values
#[derive(Debug, Deserialize)]
struct Config {
#[serde(default = "default_port")]
port: u16,
#[serde(default)]
host: String,
#[serde(default = "default_timeout")]
timeout: u64,
}
fn default_port() -> u16 { 8080 }
fn default_timeout() -> u64 { 30 }
// 4. Custom Field Names
/// Deserialize with renamed fields
#[derive(Debug, Deserialize)]
struct ApiUser {
#[serde(rename = "userId")]
id: u32,
#[serde(rename = "userName")]
name: String,
#[serde(rename = "userEmail")]
email: String,
}
// 5. Deserialize Enums
/// Deserialize simple enum
#[derive(Debug, Deserialize, Serialize)]
enum Status {
Active,
Inactive,
Pending,
}
/// Deserialize enum with data
#[derive(Debug, Deserialize, Serialize)]
enum Message {
Text(String),
Image { url: String, size: u32 },
Video { url: String, duration: u32 },
}
// 6. Deserialize with Validation
/// Deserialize age with validation
fn deserialize_age<'de, D>(deserializer: D) -> Result<u32, D::Error>
where
D: Deserializer<'de>,
{
let age = u32::deserialize(deserializer)?;
if age > 150 {
return Err(serde::de::Error::custom("Age must be <= 150"));
}
Ok(age)
}
#[derive(Debug, Deserialize)]
struct ValidatedPerson {
name: String,
#[serde(deserialize_with = "deserialize_age")]
age: u32,
email: String,
}
// 7. Deserialize to Dynamic Value
/// Deserialize to generic Value
fn deserialize_to_value(json: &str) -> Result<Value, serde_json::Error> {
from_str(json)
}
/// Extract field from JSON
fn extract_field(json: &str, field: &str) -> Option<Value> {
let v: Value = from_str(json).ok()?;
v.get(field).cloned()
}
/// Extract nested field
fn extract_nested_field(json: &str, path: &[&str]) -> Option<Value> {
let mut v: Value = from_str(json).ok()?;
for key in path {
v = v.get(key)?.clone();
}
Some(v)
}
// 8. Deserialize with Transformation
/// Deserialize and transform date string
fn deserialize_date<'de, D>(deserializer: D) -> Result<chrono::NaiveDate, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d")
.map_err(serde::de::Error::custom)
}
#[derive(Debug, Deserialize)]
struct Event {
name: String,
#[serde(deserialize_with = "deserialize_date")]
date: chrono::NaiveDate,
}
// 9. Deserialize Enums with Tag
/// Deserialize enum with type tag
#[derive(Debug, Deserialize, Serialize)]
enum Animal {
Dog { name: String, breed: String },
Cat { name: String, indoor: bool },
Bird { name: String, can_fly: bool },
}
// 10. Error Handling
/// Deserialize with helpful error message
fn deserialize_safe<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T, String> {
from_str(json).map_err(|e| format!("Failed to deserialize: {}", e))
}
/// Try multiple formats
fn deserialize_flexibly<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T, String> {
// Try standard format
if let Ok(result) = from_str(json) {
return Ok(result);
}
// Try with relaxed rules
// Add more fallback logic here if needed
Err("All deserialization attempts failed".to_string())
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust JSON Deserialization Examples ===\n");
// 1. Basic deserialization
println!("--- 1. Basic Deserialization ---");
let json_person = r#"{"name":"Alice","age":30,"email":"[email protected]","active":true}"#;
let person: Person = deserialize_from_json(json_person)?;
println!("Deserialized: {:?}", person);
// 2. Deserialize collections
println!("\n--- 2. Deserialize Collections ---");
let json_array = r#"[1,2,3,4,5]"#;
let numbers: Vec<i32> = deserialize_to_vector(json_array)?;
println!("Numbers: {:?}", numbers);
let json_object = r#"{"key1":"value1","key2":"value2"}"#;
let map: HashMap<String, String> = deserialize_to_map(json_object)?;
println!("Map: {:?}", map);
// 3. Optional fields
println!("\n--- 3. Optional Fields ---");
let json_profile = r#"{"username":"alice","active":true}"#;
let profile: UserProfile = deserialize_from_json(json_profile)?;
println!("Profile: {:?}", profile);
// 4. Default values
println!("\n--- 4. Default Values ---");
let json_config = r#"{"host":"localhost"}"#;
let config: Config = deserialize_from_json(json_config)?;
println!("Config: {:?}", config);
// 5. Renamed fields
println!("\n--- 5. Renamed Fields ---");
let json_user = r#"{"userId":1,"userName":"Bob","userEmail":"[email protected]"}"#;
let user: ApiUser = deserialize_from_json(json_user)?;
println!("User: {:?}", user);
// 6. Enums
println!("\n--- 6. Deserialize Enums ---");
let json_status = r#""Active""#;
let status: Status = deserialize_from_json(json_status)?;
println!("Status: {:?}", status);
// 7. Dynamic value
println!("\n--- 7. Dynamic Value ---");
let json_dynamic = r#"{"name":"Charlie","age":25,"city":"NYC"}"#;
let v: Value = deserialize_to_value(json_dynamic)?;
println!("Value: {}", v);
if let Some(name) = extract_field(json_dynamic, "name") {
println!("Extracted name: {}", name);
}
// 8. Validation
println!("\n--- 8. Validation ---");
let json_valid = r#"{"name":"David","age":30,"email":"[email protected]"}"#;
match deserialize_from_json::<ValidatedPerson>(json_valid) {
Ok(person) => println!("Valid person: {:?}", person),
Err(e) => println!("Error: {}", e),
}
// 9. Transformation
println!("\n--- 9. Transformation ---");
let json_event = r#"{"name":"Conference","date":"2024-06-15"}"#;
let event: Event = deserialize_from_json(json_event)?;
println!("Event: {:?}", event);
// 10. Error handling
println!("\n--- 10. Error Handling ---");
let invalid_json = r#"{"invalid":"data"}"#;
match deserialize_safe::<Person>(invalid_json) {
Ok(person) => println!("Person: {:?}", person),
Err(e) => println!("Error: {}", e),
}
println!("\n=== All JSON Deserialization Examples Completed ===");
Ok(())
}
💻 XML解析 rust
🟡 intermediate
⭐⭐⭐
使用quick-xml crate解析和操作XML文档
⏱️ 25 min
🏷️ rust, web, serialization, xml
Prerequisites:
Intermediate Rust, quick-xml crate
// Web Rust XML Parsing Examples
// Parse and manipulate XML documents
//
// Add to Cargo.toml:
// [dependencies]
// quick-xml = "0.31"
use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText};
use quick_xml::Writer;
use std::io::Cursor;
// 1. Basic XML Parsing
/// Parse XML and extract element content
fn parse_element_content(xml: &str, element_name: &str) -> Result<Option<String>, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut in_element = false;
let mut content = None;
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(ref e) => {
if e.name().as_ref() == element_name.as_bytes() {
in_element = true;
}
}
Event::Text(e) if in_element => {
content = Some(e.unescape()?.into_owned());
}
Event::End(ref e) => {
if e.name().as_ref() == element_name.as_bytes() {
in_element = false;
break;
}
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(content)
}
/// Extract all elements with specific tag
fn extract_elements(xml: &str, tag: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut elements = Vec::new();
let mut in_target = false;
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(ref e) => {
if e.name().as_ref() == tag.as_bytes() {
in_target = true;
}
}
Event::Text(e) if in_target => {
elements.push(e.unescape()?.into_owned());
}
Event::End(ref e) => {
if e.name().as_ref() == tag.as_bytes() {
in_target = false;
}
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(elements)
}
// 2. Parse XML Attributes
/// Extract attributes from an element
fn extract_attributes(xml: &str, element: &str) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut attributes = Vec::new();
let mut buf = Vec::new();
let mut reader = reader;
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(e) => {
if e.name().as_ref() == element.as_bytes() {
for attr in e.attributes() {
let attr = attr?;
let key = std::str::from_utf8(attr.key.as_ref())?.to_string();
let value = attr.unescape_value()?.to_string();
attributes.push((key, value));
}
break;
}
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(attributes)
}
// 3. Parse Nested Structures
/// Person struct parsed from XML
#[derive(Debug)]
struct Person {
name: String,
age: u32,
email: String,
}
/// Parse person from XML
fn parse_person(xml: &str) -> Result<Person, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut current_element = String::new();
let mut name = String::new();
let mut age = String::new();
let mut email = String::new();
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(e) => {
current_element = std::str::from_utf8(e.name().as_ref())?.to_string();
}
Event::Text(e) => {
match current_element.as_str() {
"name" => name = e.unescape()?.into_owned(),
"age" => age = e.unescape()?.into_owned(),
"email" => email = e.unescape()?.into_owned(),
_ => {}
}
}
Event::End(_) => {
current_element.clear();
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(Person {
name,
age: age.parse()?,
email,
})
}
// 4. Build XML
/// Create simple XML element
fn build_element(name: &str, content: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut writer = Writer::new(Cursor::new(Vec::new()));
writer.write_event(Event::Start(BytesStart::new(name)))?;
writer.write_event(Event::Text(BytesText::new(content)))?;
writer.write_event(Event::End(BytesEnd::new(name)))?;
let result = writer.into_inner().into_inner();
Ok(String::from_utf8(result)?)
}
/// Create XML with attributes
fn build_element_with_attrs(
name: &str,
attrs: &[(&str, &str)],
content: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let mut writer = Writer::new(Cursor::new(Vec::new()));
let mut elem = BytesStart::new(name);
for (key, value) in attrs {
elem.push_attribute((*key, *value));
}
writer.write_event(Event::Start(elem))?;
writer.write_event(Event::Text(BytesText::new(content)))?;
writer.write_event(Event::End(BytesEnd::new(name)))?;
let result = writer.into_inner().into_inner();
Ok(String::from_utf8(result)?)
}
// 5. XML to Struct Conversion
/// Book struct
#[derive(Debug)]
struct Book {
title: String,
author: String,
year: u32,
}
/// Parse book from XML
fn parse_book(xml: &str) -> Result<Book, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut current = String::new();
let mut title = String::new();
let mut author = String::new();
let mut year = String::new();
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(e) => {
current = std::str::from_utf8(e.name().as_ref())?.to_string();
}
Event::Text(e) => {
match current.as_str() {
"title" => title = e.unescape()?.into_owned(),
"author" => author = e.unescape()?.into_owned(),
"year" => year = e.unescape()?.into_owned(),
_ => {}
}
}
Event::End(_) => current.clear(),
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(Book {
title,
author,
year: year.parse()?,
})
}
// 6. Serialize to XML
/// Convert book to XML
fn book_to_xml(book: &Book) -> Result<String, Box<dyn std::error::Error>> {
let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 4);
writer.write_event(Event::Decl(BytesStart::new("version="1.0" encoding="UTF-8"")))?;
let mut root = BytesStart::new("book");
writer.write_event(Event::Start(root))?;
let mut title_elem = BytesStart::new("title");
writer.write_event(Event::Start(title_elem))?;
writer.write_event(Event::Text(BytesText::new(&book.title)))?;
writer.write_event(Event::End(BytesEnd::new("title")))?;
let mut author_elem = BytesStart::new("author");
writer.write_event(Event::Start(author_elem))?;
writer.write_event(Event::Text(BytesText::new(&book.author)))?;
writer.write_event(Event::End(BytesEnd::new("author")))?;
let mut year_elem = BytesStart::new("year");
writer.write_event(Event::Start(year_elem))?;
writer.write_event(Event::Text(BytesText::new(&book.year.to_string())))?;
writer.write_event(Event::End(BytesEnd::new("year")))?;
writer.write_event(Event::End(BytesEnd::new("book")))?;
let result = writer.into_inner().into_inner();
Ok(String::from_utf8(result)?)
}
// 7. Extract CDATA
/// Extract CDATA content
fn extract_cdata(xml: &str) -> Result<Option<String>, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut cdata_content = None;
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::CData(e) => {
cdata_content = Some(e.to_string());
break;
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(cdata_content)
}
// 8. Extract Comments
/// Extract all XML comments
fn extract_comments(xml: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let reader = quick_xml::Reader::from_str(xml);
let mut comments = Vec::new();
let mut reader = reader;
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Comment(e) => {
comments.push(e.to_string());
}
Event::Eof => break,
_ => {}
}
buf.clear();
}
Ok(comments)
}
// 9. Build Complex XML
/// Build nested XML structure
fn build_catalog_xml(books: &[Book]) -> Result<String, Box<dyn std::error::Error>> {
let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 2);
writer.write_event(Event::Decl(BytesStart::new("version="1.0" encoding="UTF-8"")))?;
let mut catalog = BytesStart::new("catalog");
writer.write_event(Event::Start(catalog))?;
for book in books {
let mut book_elem = BytesStart::new("book");
writer.write_event(Event::Start(book_elem))?;
// Title
let mut title = BytesStart::new("title");
writer.write_event(Event::Start(title))?;
writer.write_event(Event::Text(BytesText::new(&book.title)))?;
writer.write_event(Event::End(BytesEnd::new("title")))?;
// Author
let mut author = BytesStart::new("author");
writer.write_event(Event::Start(author))?;
writer.write_event(Event::Text(BytesText::new(&book.author)))?;
writer.write_event(Event::End(BytesEnd::new("author")))?;
// Year
let mut year = BytesStart::new("year");
writer.write_event(Event::Start(year))?;
writer.write_event(Event::Text(BytesText::new(&book.year.to_string())))?;
writer.write_event(Event::End(BytesEnd::new("year")))?;
writer.write_event(Event::End(BytesEnd::new("book")))?;
}
writer.write_event(Event::End(BytesEnd::new("catalog")))?;
let result = writer.into_inner().into_inner();
Ok(String::from_utf8(result)?)
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust XML Parsing Examples ===\n");
// 1. Parse element content
println!("--- 1. Parse Element Content ---");
let xml = r#"<root><greeting>Hello, World!</greeting></root>"#;
match parse_element_content(xml, "greeting") {
Ok(Some(content)) => println!("Greeting: {}", content),
_ => println!("Not found"),
}
// 2. Extract all elements
println!("\n--- 2. Extract All Elements ---");
let xml = r#"<root><item>Apple</item><item>Banana</item><item>Orange</item></root>"#;
let items = extract_elements(xml, "item")?;
println!("Items: {:?}", items);
// 3. Extract attributes
println!("\n--- 3. Extract Attributes ---");
let xml = r#"<person id="1" name="Alice" age="30" />"#;
let attrs = extract_attributes(xml, "person")?;
println!("Attributes: {:?}", attrs);
// 4. Parse person
println!("\n--- 4. Parse Structured Data ---");
let xml = r#"
<person>
<name>Bob</name>
<age>25</age>
<email>[email protected]</email>
</person>
"#;
let person = parse_person(xml)?;
println!("Person: {:?}", person);
// 5. Build XML
println!("\n--- 5. Build XML ---");
let xml = build_element("message", "Hello, XML!")?;
println!("Simple element: {}", xml);
let xml_with_attrs = build_element_with_attrs(
"user",
&[("id", "1"), ("name", "Alice")],
"Content",
)?;
println!("With attributes: {}", xml_with_attrs);
// 6. Parse and build book
println!("\n--- 6. Book Serialization ---");
let xml = r#"<book><title>Rust Programming</title><author>Steve Klabnik</author><year>2023</year></book>"#;
let book = parse_book(xml)?;
println!("Parsed book: {:?}", book);
let book_xml = book_to_xml(&book)?;
println!("Serialized:\n{}", book_xml);
// 7. Build catalog
println!("\n--- 7. Build Complex XML ---");
let books = vec![
Book {
title: "The Rust Book".to_string(),
author: "Steve Klabnik".to_string(),
year: 2023,
},
Book {
title: "Programming Rust".to_string(),
author: "Jim Blandy".to_string(),
year: 2021,
},
];
let catalog_xml = build_catalog_xml(&books)?;
println!("Catalog:\n{}", catalog_xml);
println!("\n=== All XML Parsing Examples Completed ===");
Ok(())
}