MYMONDAY.ai
서비스스튜디오도구데이터·포맷73CSS 생성기19색상·이미지10인코딩·보안10웹·SEO11개발·데브옵스10파일·내보내기18계산기6가이드

XML Rust 구조체 변환기

샘플 XML에서 serde에 바로 쓸 수 있는 Rust 구조체를 만들고, rename 속성으로 속성과 텍스트의 정확한 키를 유지합니다.

  • 브라우저에서 처리
  • 가입 없음
  • 무료

도구 작업 공간

예제

옵션

XML → 데이터 매핑

속성은 이 문자로 시작하는 키가 되어 id="1"은 @id가 됩니다. 비우면 속성 이름 그대로 씁니다.

속성이나 자식 요소와 함께 있는 텍스트는 이 키에 담습니다.

끄면 <item>이 하나일 땐 객체, 여러 개일 땐 배열이 됩니다. 켜면 개수와 상관없이 구조가 같습니다.

끄면 모든 값이 문자열로 남습니다. 켜면 true/false, 정수, 소수는 해당 타입이 되고 007이나 긴 ID는 문자열로 둡니다.

XML 입력

21줄491byte

결과

⌘/Ctrl + Enter로 복사
결과 · payload.rs
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Payload {
    pub order: PayloadOrder,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrder {
    #[serde(rename = "@id")]
    pub id: i64,
    #[serde(rename = "@status")]
    pub status: String,
    pub customer: PayloadOrderCustomer,
    pub items: PayloadOrderItems,
    pub total: f64,
    pub shipped_at: String,
    pub tracking: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrderCustomer {
    #[serde(rename = "@id")]
    pub id: i64,
    #[serde(rename = "@vip")]
    pub vip: bool,
    pub name: String,
    pub email: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrderItems {
    pub item: Vec<PayloadOrderItemsItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrderItemsItem {
    #[serde(rename = "@sku")]
    pub sku: String,
    #[serde(rename = "@qty")]
    pub qty: i64,
    pub name: String,
    pub price: f64,
}
타입5
크기1kB

이 도구는 샘플 XML에 대한 Rust 구조체를 씁니다. XML 변환기들이 공유하는 규칙으로 XML을 데이터로 매핑하고, 속성이나 자식이 있는 요소마다 #[derive(Debug, Clone, Serialize, Deserialize)]가 붙은 pub struct가 생깁니다. 필드는 pub이며 이름은 스네이크 케이스입니다.

키가 올바른 Rust 이름이 아니면 필드에 #[serde(rename = "@sku")]가 붙어 serde_json이 정확한 키를 읽습니다. Rust 키워드는 r#type처럼 원시 식별자로 씁니다. 구조체는 serde_json::from_str로 읽는 변환된 JSON을 대상으로 합니다. 원본 XML을 읽으려면 quick-xml 같은 크레이트와 그쪽 규칙을 써야 합니다.

입력은 엄격한 XML 1.0 파서가 읽고 오류에는 정확한 행과 열을 알려 줍니다. 20 MiB까지의 입력이 브라우저 탭 안에 머뭅니다.

사용 방법

  1. XML 붙여넣기

    문서를 붙여 넣거나 예제를 불러옵니다. 수정하는 즉시 구조체가 따라 바뀝니다.

  2. 매핑 설정

    XML 데이터 매핑 패널에서 속성 접두사, 텍스트 키, 항상 배열, 숫자 추론을 고릅니다.

  3. Rust 옵션 정하기

    루트 구조체 이름(기본 Payload)을 입력하고, 선택 필드에 skip_serializing_if를 붙일지 정합니다.

  4. 구조체 읽기

    루트 구조체가 먼저 나옵니다. serde_json::Value import는 한 위치에 종류가 섞인 값이 있을 때만 추가됩니다.

  5. 복사 또는 다운로드

    코드를 복사하거나 루트 이름의 스네이크 케이스인 payload.rs로 내려받습니다.

작동 원리

생성되는 구조체의 타입

정수는 모두 i64, 소수는 모두 f64입니다. CDATA와 빈 요소를 포함한 텍스트는 String이므로, 007처럼 숫자처럼 보여도 매핑 규칙상 문자열인 값은 String으로 남습니다.

XMLRust
<name>Ada</name>pub name: String
id="7"#[serde(rename = "@id")] pub id: i64
<price>19.5</price>pub price: f64
<ok>true</ok>pub ok: bool
반복되는 <item>pub item: Vec<PayloadItem>
일부 item에만 있는 키pub qty: Option<i64>
<v>1</v><v>a</v>pub v: Vec<Value>, use serde_json::Value; 추가

rename, 원시 식별자, skip_serializing_if

필드 이름은 접두 문자를 뺀 키의 스네이크 케이스라서 a-b는 a_b, xml:lang은 xml_lang입니다. type이나 match 같은 단어는 r#type이 됩니다. 어느 경우든 이름 변경이 필요하면 rename 속성에 실제 키가 들어갑니다.

선택 키는 Option<T>가 됩니다. 누락된 필드는 쓰지 않기를 켜면 #[serde(default, skip_serializing_if = "Option::is_none")]도 붙어, 직렬화할 때 값이 없는 키를 생략합니다. 끄면 평범한 Option<T>가 되어 null을 씁니다.

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrderItem {
    #[serde(rename = "@sku")]
    pub sku: String,
    #[serde(rename = "@qty")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub qty: Option<i64>,
}

자식 하나일 때와 여럿일 때

<item>이 하나면 구조체 타입 필드, 여럿이면 Vec입니다. 자식 요소는 항상 배열로 옵션을 켜면 하나뿐인 샘플에서도 Vec<T>가 되어, 더 긴 문서에서 serde_json이 invalid type: map, expected a sequence 오류를 내지 않습니다.

실제 예시

반복 항목이 있는 주문
입력
<order id="1042"><item sku="A1" qty="1">Pen</item><item sku="B7">Ink</item></order>
출력
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Payload {
    pub order: PayloadOrder,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrder {
    #[serde(rename = "@id")]
    pub id: i64,
    pub item: Vec<PayloadOrderItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadOrderItem {
    #[serde(rename = "@sku")]
    pub sku: String,
    #[serde(rename = "@qty")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub qty: Option<i64>,
    #[serde(rename = "#text")]
    pub text: String,
}

합쳐진 item 구조체가 @sku, @qty, #text를 rename합니다. qty는 첫 item에만 있어 default와 skip_serializing_if가 붙은 Option<i64>입니다.

키워드와 하이픈
입력
<r><type>x</type><a-b>1</a-b></r>
출력
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Payload {
    pub r: PayloadR,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadR {
    pub r#type: String,
    #[serde(rename = "a-b")]
    pub a_b: i64,
}

type은 Rust 키워드라 rename 없이 r#type이 되고, a-b는 a_b가 되면서 rename으로 키를 유지합니다.

자식이 하나일 때 항상 배열 옵션
입력
<cart><item id="1">Pen</item></cart>
출력
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Payload {
    pub cart: PayloadCart,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadCart {
    pub item: Vec<PayloadCartItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadCartItem {
    #[serde(rename = "@id")]
    pub id: i64,
    #[serde(rename = "#text")]
    pub text: String,
}

샘플에 item이 하나뿐이어도 Vec<PayloadCartItem>이므로 item이 많은 장바구니도 같은 구조체로 역직렬화됩니다.

자주 하는 실수

  • Option이 아니면 키가 없을 때 오류입니다

    Option이 아닌 필드는 키가 없으면 missing field로 실패합니다. 샘플에서 한 번도 빠지지 않은 키는 선택이 아니므로 값이 일부만 있는 예도 붙여 넣으세요.

  • 모든 정수가 i64

    정수는 항상 i64가 됩니다. 도메인에 필요하면 u32, u64, i32로 직접 바꾸세요.

  • 정수처럼 보이는 소수

    19.0은 19로 읽혀 필드가 i64가 되고, 나중에 19.5가 오면 invalid type: floating point로 실패합니다. 추론을 끄거나 f64로 바꾸세요.

  • quick-xml 모델이 아닙니다

    serde와 쓰는 quick-xml은 @attr, $text 같은 자체 규칙을 기대하며, 여기서 쓰는 #text 키와 다릅니다.

자주 묻는 질문

어떤 크레이트가 필요한가요?

derive 기능을 켠 serde와 serde_json입니다. Value import는 한 위치에 종류가 섞인 값이 있을 때만 나타납니다.

필드 이름이 왜 r#type인가요?

type은 Rust의 예약어입니다. 원시 식별자 r#type을 쓰면 rename 없이도 필드 이름과 키가 그대로 유지됩니다.

스킵 옵션은 무엇을 하나요?

선택 필드에 default와 skip_serializing_if = "Option::is_none"을 붙여 직렬화할 때 값이 없는 키를 생략합니다.

이 구조체로 XML을 바로 읽을 수 있나요?

serde_json으로는 안 됩니다. XML to JSON 변환기 등으로 먼저 JSON으로 매핑한 뒤 serde_json::from_str를 호출하세요.

rename 값의 @를 없애려면 어떻게 하나요?

매핑 패널에서 속성 접두사를 빈 문자열로 바꾸세요. 특이한 키가 없는 필드는 rename이 아예 필요 없습니다.

업로드되는 것이 있나요?

없습니다. 파싱과 코드 생성이 페이지 안에서 로컬로 실행됩니다.

마지막 업데이트: