con un clic
serde
Rust serde + serde_json 직렬화/역직렬화 핵심 패턴
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Rust serde + serde_json 직렬화/역직렬화 핵심 패턴
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Spring Security 5.5.x + jjwt 0.10.7 레거시 JWT 인증 - WebSecurityConfigurerAdapter, OncePerRequestFilter, javax.servlet 환경
Spring Boot 3.x + Spring Security 6.x + jjwt 0.12.x 기반 모던 JWT 인증 패턴. SecurityFilterChain Bean, 람다 DSL, jakarta.servlet, Virtual Threads 적용
Unity 6 LTS 2D 모바일 게임용 uGUI 시스템 전문 스킬. Canvas/RectTransform/TextMeshPro, 모바일 UI 패턴(팝업·무한 스크롤·광고·IAP), 성능 최적화, UI Toolkit과의 선택 기준 포함.
아크라시아(akrasia, 자제력 없음) 학술 논쟁의 핵심 구도와 주요 연구자·문헌을 빠르게 파악할 수 있는 도메인 지식 스킬. 도덕윤리교육 전공 대학원생(석/박사)이 학위논문·KCI 투고·세미나 준비 시 고대–현대–한국 학계–도덕심리학 흐름을 한 번에 짚도록 구성. <example>사용자: "아리스토텔레스의 propeteia와 astheneia 구분을 인용하려는데 출처를 알려줘"</example> <example>사용자: "데이비슨이 의지박약을 어떻게 가능하다고 봤는지 핵심 논증을 정리해줘"</example> <example>사용자: "한국 도덕교육 학계에서 아크라시아 다룬 논문 있어?"</example>
아리스토텔레스 『니코마코스 윤리학』에서 akrasia(자제력없음)와 akolasia(무절제)의 5축 차이를 정밀하게 정리한 학위논문 자료 스킬. NE VII.4 1147b20-1148b14, VII.8 1150b29-1151a28, III.10-12 1117b23-1119b18 절별 분해와 표준 학자 해석(Bostock, Broadie-Rowe, Pakaluk, Hursthouse, Charles 등)을 포함. 도덕교육 적용을 위한 두 상태 차이의 함의 및 한국어 번역어 처리 권장안 제공. <example>사용자: "akrates와 akolastos를 prohairesis 측면에서 어떻게 구분해야 하나요?"</example> <example>사용자: "NE VII.4의 ἁπλῶς akrasia가 akolasia와 어떻게 갈라지는지 절별 분해해주세요"</example> <example>사용자: "Hursthouse의 연속체 모델을 도덕교육 적용 절에서 어떻게 활용할 수 있나요?"</example>
한국 위기 대응 자원(자살·자해·정신건강·여성·청소년·노인·다문화) 핫라인과 앱·챗봇 안전 가드 응답 패턴 종합. 꿈 해몽·정신건강 앱 등 자가 진단/감정 콘텐츠 도메인에서 위험 신호 포착 시 안전한 자원 안내 문구를 작성할 때 참조. <example>사용자: "꿈 해몽 앱에 위기 안내 문구를 어떻게 넣을까?"</example> <example>사용자: "한국에서 자살예방 핫라인 번호가 어떻게 바뀌었지?"</example> <example>사용자: "정신건강 챗봇 안전 가드 응답 템플릿을 짜줘"</example>
| name | serde |
| description | Rust serde + serde_json 직렬화/역직렬화 핵심 패턴 |
소스: https://serde.rs/ , https://docs.rs/serde_json/ 검증일: 2026-06-20
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
features = ["derive"]를 반드시 활성화해야 #[derive(Serialize, Deserialize)]를 사용할 수 있다.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct User {
name: String,
age: u32,
email: String,
}
Serialize: Rust 구조체 -> 직렬화 포맷 (JSON, TOML 등)Deserialize: 직렬화 포맷 -> Rust 구조체Serialize/Deserialize를 구현해야 동작한다.String, Vec<T>, HashMap<K,V>, Option<T> 등)은 이미 구현되어 있다.let user = User { name: "Alice".into(), age: 30, email: "alice@example.com".into() };
// 일반 JSON 문자열
let json = serde_json::to_string(&user)?;
// {"name":"Alice","age":30,"email":"alice@example.com"}
// 보기 좋게 포맷팅
let pretty = serde_json::to_string_pretty(&user)?;
let json = r#"{"name":"Alice","age":30,"email":"alice@example.com"}"#;
let user: User = serde_json::from_str(json)?;
// &[u8] -> T
let user: User = serde_json::from_slice(bytes)?;
// T -> Vec<u8>
let bytes = serde_json::to_vec(&user)?;
// Read trait -> T
let user: User = serde_json::from_reader(reader)?;
// T -> Write trait
serde_json::to_writer(writer, &user)?;
serde_json::to_writer_pretty(writer, &user)?;
반환 타입: 모든 함수는 serde_json::Result<T>를 반환한다. ? 연산자 또는 unwrap()으로 처리.
구조체 없이 임의의 JSON을 다룰 때 사용한다.
use serde_json::Value;
let data: Value = serde_json::from_str(r#"{"name":"Alice","age":30}"#)?;
// 인덱스 접근 (존재하지 않으면 Value::Null 반환)
println!("{}", data["name"]); // "Alice"
println!("{}", data["age"]); // 30
println!("{}", data["missing"]); // null
use serde_json::json;
let value = json!({
"name": "Alice",
"age": 30,
"tags": ["rust", "serde"],
"address": {
"city": "Seoul"
}
});
enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
// as_ 메서드 (Option 반환)
data["name"].as_str(); // Option<&str>
data["age"].as_u64(); // Option<u64>
data["age"].as_i64(); // Option<i64>
data["age"].as_f64(); // Option<f64>
data["flag"].as_bool(); // Option<bool>
data["arr"].as_array(); // Option<&Vec<Value>>
data["obj"].as_object(); // Option<&Map<String, Value>>
// Value -> 구조체 (serde_json::from_value)
let user: User = serde_json::from_value(value)?;
// 구조체 -> Value (serde_json::to_value)
let value = serde_json::to_value(&user)?;
#[derive(Serialize, Deserialize)]
struct User {
#[serde(rename = "userName")]
user_name: String,
// 직렬화/역직렬화 각각 다른 이름
#[serde(rename(serialize = "output_name", deserialize = "input_name"))]
name: String,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ApiResponse {
user_name: String, // JSON: "userName"
created_at: String, // JSON: "createdAt"
}
지원되는 rename_all 규칙:
| 값 | 입력 user_name -> 출력 |
|---|---|
"camelCase" | userName |
"PascalCase" | UserName |
"snake_case" | user_name |
"SCREAMING_SNAKE_CASE" | USER_NAME |
"kebab-case" | user-name |
"SCREAMING-KEBAB-CASE" | USER-NAME |
"lowercase" | username |
"UPPERCASE" | USERNAME |
조건에 따라 직렬화에서 필드를 제외한다.
#[derive(Serialize, Deserialize)]
struct Config {
name: String,
// None이면 JSON 출력에서 제외
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
// 빈 Vec이면 제외 + 역직렬화 시 필드 없어도 허용
#[serde(default, skip_serializing_if = "Vec::is_empty")]
tags: Vec<String>,
// 커스텀 함수 사용 + 역직렬화 시 필드 없어도 허용
#[serde(default, skip_serializing_if = "is_zero")]
count: u32,
}
fn is_zero(v: &u32) -> bool {
*v == 0
}
// 주의: skip_serializing_if는 직렬화에만 영향을 준다.
// Option<T> 필드는 Serde가 특수 처리하여 #[serde(default)] 없이도 누락 시 자동으로 None으로 처리된다.
// Option<T> 외 타입(String, u32, Vec<T> 등)에서 필드 누락을 허용하려면 #[serde(default)]를 반드시 함께 써야 한다.
JSON에 필드가 없을 때 기본값을 사용한다.
#[derive(Serialize, Deserialize)]
struct Config {
name: String,
// 필드 없으면 Default::default() 사용 (u32는 0)
#[serde(default)]
retry_count: u32,
// 커스텀 기본값 함수
#[serde(default = "default_timeout")]
timeout: u64,
}
fn default_timeout() -> u64 {
30
}
#[derive(Serialize, Deserialize)]
struct Internal {
pub name: String,
#[serde(skip)] // 직렬화, 역직렬화 모두 제외
cache: Vec<u8>,
#[serde(skip_serializing)] // 직렬화만 제외
password: String,
#[serde(skip_deserializing)] // 역직렬화만 제외
computed: String,
}
skip, skip_deserializing 사용 시 해당 필드는 Default trait 구현이 필요하다.
#[derive(Serialize, Deserialize, Debug)]
struct Address {
city: String,
zip: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Company {
name: String,
address: Address,
}
#[derive(Serialize, Deserialize, Debug)]
struct Employee {
name: String,
company: Company,
skills: Vec<String>,
}
{
"name": "Alice",
"company": {
"name": "Acme",
"address": {
"city": "Seoul",
"zip": "06000"
}
},
"skills": ["rust", "typescript"]
}
#[derive(Serialize, Deserialize)]
struct Pagination {
page: u32,
per_page: u32,
}
#[derive(Serialize, Deserialize)]
struct UserQuery {
name: String,
#[serde(flatten)]
pagination: Pagination,
}
// JSON: {"name":"Alice","page":1,"per_page":20}
// (pagination 키 없이 필드가 상위에 펼쳐짐)
use std::collections::HashMap;
#[derive(Serialize, Deserialize)]
struct Known {
name: String,
age: u32,
#[serde(flatten)]
extra: HashMap<String, serde_json::Value>,
}
// 정의되지 않은 필드가 extra에 자동 수집됨
| 속성 | 위치 | 용도 |
|---|---|---|
rename_all | 구조체/열거형 | 전체 필드명 규칙 변환 |
deny_unknown_fields | 구조체 | 정의되지 않은 필드가 있으면 에러 |
tag | 열거형 | 태그 기반 직렬화 ("type": "variant") |
untagged | 열거형 | 태그 없이 내용만으로 variant 판별 |
content | 열거형 | tag와 함께 사용. 데이터를 별도 키에 |
default | 구조체 | 모든 필드에 Default 적용 |
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum Message {
Text { body: String },
Image { url: String, width: u32 },
}
// {"type":"Text","body":"hello"}
#[derive(Serialize, Deserialize)]
#[serde(tag = "type", content = "data")]
enum Event {
Click { x: i32, y: i32 },
KeyPress(char),
}
// {"type":"Click","data":{"x":10,"y":20}}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum StringOrInt {
Str(String),
Int(i64),
}
// "hello" 또는 42 (태그 없이 값으로 판별)
주의:
untaggedenum은 variant 순서대로 역직렬화를 시도하므로, 먼저 매치되는 variant가 선택된다. 순서에 주의할 것.