나는 java 언어를 주로 다루는 백엔드 개발자 이다. 그냥 개발자이다. 백기선 님 , 김영한 님 이런 유명 개발자가 아닌 그냥 똥 개발자이다. 그럼에도 불구하고 직렬화 와 역질렬화에 대한 개발기초 지식은 있으니 이 글을 읽는 개발자 분들도 어느정도 알거라 믿고 닥치고 RUST 에서 직렬화 , 역질화 다루는 법을 알아보자.
Serde 란?
Serde는 Rust 데이터 구조를 직렬화 및 역직렬화하는 라이브러리입니다. 이는 JSON, BSON, YAML 등 다양한 형식을 지원하며, 직렬화 및 역직렬화 방법을 사용자 정의할 수 있습니다. Serde는 간결하고 사용하기 쉬우며 효율적인 성능을 가지고 있어 Rust 생태계에서 가장 인기있는 직렬화 라이브러리 중 하나입니다.
기본 사용법
- 설치
Rust 프로젝트에서 Serde를 사용하려면 Cargo.toml 파일에 다음 종속성을 추가해야 합니다.
[dependencies]
serde = { version = "1.0", features = ["derive"] }
여기서 features = ["derive"]는 Serde의 파생 매크로를 사용하며, 직렬화 및 역직렬화 코드를 자동으로 생성할 수 있습니다.
- 직렬화
Serde를 사용하여 직렬화하려면 먼저 데이터 구조를 serde::Serialize trait로 구현해야 합니다. 예를 들어, 이름과 나이 두 가지 필드를 포함하는 Animal 구조체를 정의합니다.
#[derive(Serialize)]
struct Animal {
name: String,
age: u32,
}
그런 다음 serde_json 라이브러리를 사용하여 Animal 구조체를 JSON 문자열로 직렬화할 수 있습니다.
use serde_json;
let animal = Animal {
name: "Tom".to_owned(),
age: 3,
};
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"name":"Tom","age":3}
- 역직렬화
Serde를 사용하여 역직렬화하려면 먼저 데이터 구조를 serde::Deserialize trait로 구현해야 합니다. 예를 들어, 이름과 나이 두 가지 필드를 포함하는 Animal 구조체를 정의합니다.
#[derive(Deserialize)]
struct Animal {
name: String,
age: u32,
}
그런 다음 serde_json 라이브러리를 사용하여 JSON 문자열을 Animal 구조체로 역직렬화할 수 있습니다.
use serde_json;
let json = r#"{"name":"Tom","age":3}"#;
let animal: Animal = serde_json::from_str(json).unwrap();
println!("{:?}", animal); // Animal { name: "Tom", age: 3 }
직렬화 및 역직렬화를 사용자 정의하는 방법을 보여주는 Rust 코드입니다.
use serde::{Serialize, Deserialize, Serializer, Deserializer};
#[derive(Serialize, Deserialize)]
struct Animal {
#[serde(serialize_with = "serialize_name", deserialize_with = "deserialize_name")]
name: String,
age: u32,
}
fn serialize_name<S>(name: &String, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&name.to_uppercase())
}
fn deserialize_name<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let name = String::deserialize(deserializer)?;
Ok(name.to_lowercase())
}
위의 Rust 코드는 Animal 구조체를 정의하고 이름(name)과 나이(age) 두 개의 필드를 포함합니다. 하지만 직렬화(Serialization)할 때 이름을 대문자로 변환하고, 역직렬화(Deserialization)할 때 이름을 소문자로 변환하도록 사용자 지정 직렬화 및 역직렬화 방법을 사용하고자 합니다.
Animal 구조체 내에서 #[serde(serialize_with = "serialize_name", deserialize_with = "deserialize_name")]를 사용하여 사용자 지정 직렬화 및 역직렬화 방법을 지정합니다. serialize_name 함수는 이름을 대문자로 변환하고 deserialize_name 함수는 이름을 소문자로 변환합니다.
또한 Serde는 열거형(Enum) 타입의 직렬화 및 역직렬화를 지원합니다. Animal 열거형을 정의하고, 개(Dog)와 고양이(Cat) 두 가지 유형을 포함시킵니다.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
enum Animal {
Dog { name: String, age: u32 },
Cat { name: String, age: u32 },
}
열거형(Enum) 타입을 직렬화 및 역직렬화할 때, #[serde(tag = "type")]를 사용하여 열거형(Enum) 타입의 레이블을 지정해야 합니다. 예를 들어:
use serde_json;
let dog = Animal::Dog { name: "Tom".to_owned(), age: 3 };
let json = serde_json::to_string(&dog).unwrap();
println!("{}", json); // {"type":"Dog","name":"Tom","age":3}
let json = r#"{"type":"Dog","name":"Tom","age":3}"#;
let dog: Animal = serde_json::from_str(json).unwrap();
println!("{:?}", dog); // Dog { name: "Tom", age: 3 }
위 코드는 Animal 열거형의 Dog 타입을 생성하고 이름이 "Tom"이며 나이가 3인 개(Dog)를 만듭니다.
해당 값을 JSON 형식으로 직렬화(serialization)하여 출력합니다. 그리고 다시 JSON 문자열을 역직렬화(deserialization)하여 Animal 열거형의 값을 얻습니다. 이렇게 출력된 결과를 확인해보면, Dog 타입이 생성되고, 이름은 "Tom", 나이는 3인 Animal이 만들어진 것을 확인할 수 있습니다.
Option 타입 직렬화 및 역직렬화
Serde는 Option 타입의 직렬화와 역직렬화를 지원합니다. 예를 들어, Animal 구조체를 정의할 때, name 필드는 None일 수 있습니다.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Animal {
name: Option<String>,
age: u32,
}
Option 값을 직렬화하려면, skip_serializing_if
속성을 사용하여 None일 때 해당 값을 생략하도록 지정해야 합니다.
use serde_json;
let animal = Animal { name: Some("Tom".to_owned()), age: 3 };
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"name":"Tom","age":3}
let animal = Animal { name: None, age: 3 };
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"age":3}
Vec 타입 직렬화 및 역직렬화
Serde는 Vec 타입의 직렬화와 역직렬화를 자동으로 처리합니다. 예를 들어, Zoo 구조체를 정의할 때, 여러 개의 Animal이 포함될 수 있습니다.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Zoo {
animals: Vec<Animal>,
}
- Vec 값을 직렬화하려면,
serde_json::to_string
함수를 호출하면 됩니다.
let zoo = Zoo { animals: vec![
Animal { name: "Tom".to_owned(), age: 3 },
Animal { name: "Jerry".to_owned(), age: 2 },
] };
let json = serde_json::to_string(&zoo).unwrap();
println!("{}", json); // {"animals":[{"name":"Tom","age":3},{"name":"Jerry","age":2}]}
- Vec 값을 역직렬화하려면,
serde_json::from_str
함수를 호출하면 됩니다.
let json = r#"{"animals":[{"name":"Tom","age":3},{"name":"Jerry","age":2}]}"#;
let zoo: Zoo = serde_json::from_str(json).unwrap();
println!("{:?}", zoo); // Zoo { animals: [Animal { name: "Tom", age: 3 }, Animal { name: "Jerry", age: 2 }] }
Serde는 HashMap 타입의 직렬화 및 역직렬화를 지원합니다. 예를 들어, 다음과 같이 HashMap을 사용하여 여러 Animal을 저장하는 Zoo 구조체를 정의할 수 있습니다.
rustCopy code
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Zoo {
animals: HashMap<String, Animal>,
}
#[derive(Serialize, Deserialize)]
struct Animal {
name: String,
age: u32,
}
HashMap을 포함한 구조체를 직렬화 및 역직렬화 할 때, Serde는 자동으로 처리합니다. 예를 들어 다음과 같이 HashMap에 "Tom"과 "Jerry"라는 두 개의 key-value 쌍을 추가하고, 이 HashMap을 Zoo 구조체에 저장한 다음, 이를 JSON 문자열로 직렬화할 수 있습니다.
use serde_json;
let mut animals = HashMap::new();
animals.insert("Tom".to_owned(), Animal { name: "Tom".to_owned(), age: 3 });
animals.insert("Jerry".to_owned(), Animal { name: "Jerry".to_owned(), age: 2 });
let zoo = Zoo { animals };
let json = serde_json::to_string(&zoo).unwrap();
println!("{}", json); // {"animals":{"Jerry":{"name":"Jerry","age":2},"Tom":{"name":"Tom","age":3}}}
이어서, JSON 문자열을 Zoo 구조체로 역직렬화할 수 있습니다.
let json = r#"{"animals":{"Jerry":{"name":"Jerry","age":2},"Tom":{"name":"Tom","age":3}}}"#;
let zoo: Zoo = serde_json::from_str(json).unwrap();
println!("{:?}", zoo); // Zoo { animals: {"Tom": Animal { name: "Tom", age: 3 }, "Jerry": Animal { name: "Jerry", age: 2 }} }
챕터를 마치며…
이 튜토리얼에서는 Serde를 사용하여 직렬화와 역직렬화하는 방법을 소개하고, 사용자 정의 직렬화 및 역직렬화 로직을 작성하는 방법을 설명합니다. Serde를 사용하면 Rust 데이터 구조를 어떤 형식으로든 쉽게 변환할 수 있으며, 사용자 정의 직렬화 및 역직렬화 로직을 통해 더 고급 기능을 구현할 수 있습니다.
내저장소 바로가기 luxury515
'Back-end > Rust' 카테고리의 다른 글
Rust 아는 척 해보기-2 프로젝트 생성 (0) | 2023.04.16 |
---|---|
Rust 아는 척 해보기-1 설치 및 개발환경세팅 (0) | 2023.04.16 |