dataclass-macro 0.1.0

A procedural macro for generating dataclasses in Rust.
Documentation
# Serde Integration Guide

## Setup

First, add the required dependencies to your `Cargo.toml`:

```toml
[dependencies]
dataclass-macro = { version = "0.1.0", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"  # for JSON serialization/deserialization
```

## Basic Example

```rust
use dataclass_macro::dataclass;
use serde_json::json;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[dataclass]
struct User {
    name: String,
    age: i32,
    email: Option<String>,
    roles: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new instance
    let user = User::new(
        String::from("Alice"),
        30,
        Some(String::from("alice@example.com")),
        vec![String::from("admin"), String::from("user")]
    );

    // Serialize to JSON
    let json = serde_json::to_string_pretty(&user)?;
    println!("Serialized JSON:\n{}", json);

    // Deserialize from JSON
    let deserialized: User = serde_json::from_str(&json)?;
    assert_eq!(user, deserialized);

    Ok(())
}
```

Output:
```json
{
  "name": "Alice",
  "age": 30,
  "email": "alice@example.com",
  "roles": [
    "admin",
    "user"
  ]
}
```

## Custom Serialization

You can customize the serialization behavior using serde attributes:

```rust
use dataclass_macro::dataclass;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[dataclass]
struct Configuration {
    #[serde(rename = "serverName")]
    server_name: String,
    
    #[serde(default = "default_port")]
    port: u16,
    
    #[serde(skip_serializing_if = "Vec::is_empty")]
    tags: Vec<String>,
    
    #[serde(skip)]
    internal_data: String,
}

fn default_port() -> u16 {
    8080
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration::new(
        String::from("production-server"),
        3000,
        vec![],
        String::from("internal")
    );

    let json = serde_json::to_string_pretty(&config)?;
    println!("Config JSON:\n{}", json);

    // The JSON will not include empty tags and internal_data
    // The server_name field will be serialized as "serverName"

    Ok(())
}
```

## Working with Complex Types

```rust
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use dataclass_macro::dataclass;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[dataclass]
struct AuditLog {
    #[serde(with = "chrono::serde::ts_seconds")]
    timestamp: DateTime<Utc>,
    
    user_id: String,
    
    #[serde(flatten)]
    metadata: HashMap<String, String>,
    
    #[serde(skip_serializing_if = "Option::is_none")]
    details: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut metadata = HashMap::new();
    metadata.insert(String::from("ip"), String::from("192.168.1.1"));
    metadata.insert(String::from("browser"), String::from("Firefox"));

    let log = AuditLog::new(
        Utc::now(),
        String::from("user123"),
        metadata,
        Some(String::from("Login successful"))
    );

    let json = serde_json::to_string_pretty(&log)?;
    println!("Audit Log:\n{}", json);

    Ok(())
}
```

## Custom Enum Support

```rust
use dataclass_macro::dataclass;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum Status {
    Active,
    Inactive,
    Pending,
}

#[dataclass]
struct Account {
    id: String,
    status: Status,
    
    #[serde(skip_serializing_if = "Option::is_none")]
    last_login: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let account = Account::new(
        String::from("acc_123"),
        Status::Active,
        Some(String::from("2024-01-01"))
    );

    // Serialize to JSON
    let json = serde_json::to_string_pretty(&account)?;
    println!("Account JSON:\n{}", json);

    // Deserialize from JSON string
    let json_str = r#"{
        "id": "acc_456",
        "status": "pending",
        "last_login": null
    }"#;
    
    let deserialized: Account = serde_json::from_str(json_str)?;
    println!("Deserialized account: {:?}", deserialized);

    Ok(())
}
```

## Integration with Different Formats

```rust
use dataclass_macro::dataclass;
use std::fs::File;

#[derive(Serialize, Deserialize)]
#[dataclass]
struct Settings {
    app_name: String,
    debug_mode: bool,
    max_connections: u32,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let settings = Settings::new(
        String::from("MyApp"),
        true,
        100
    );

    // JSON
    let json = serde_json::to_string_pretty(&settings)?;
    
    // YAML
    let yaml = serde_yaml::to_string(&settings)?;
    
    // TOML
    let toml = toml::to_string_pretty(&settings)?;
    
    // Write to files
    serde_json::to_writer_pretty(
        File::create("settings.json")?,
        &settings
    )?;
    
    serde_yaml::to_writer(
        File::create("settings.yaml")?,
        &settings
    )?;

    println!("Settings in different formats:");
    println!("\nJSON:\n{}", json);
    println!("\nYAML:\n{}", yaml);
    println!("\nTOML:\n{}", toml);

    Ok(())
}
```