rust serde_json 사용법

wangki·2025년 2월 18일
0

Rust

목록 보기
21/55

개요

serde_json으로 데이터 파싱하는것을 정리하겠다.
특히 json파일에서 필드값이 없는 경우를 serde_jsonValue를 활용하여 파싱하는법을 알아보겠다.

과정

아래 json 데이터를 살펴보자.

[
    [100.0, 102.1, 98.5, 101.3],
    [101.3, 103.5, 99.2, 102.7],
    [102.7, 105.0, 100.8, 104.2],
    [104.2, 106.3, 102.5, 105.8],
    [105.8, 108.1, 103.9, 107.5],
    [107.5, 109.7, 105.6, 108.9],
    [108.9, 111.2, 107.1, 110.3],
    [110.3, 113.0, 108.8, 112.5],
    [112.5, 115.4, 110.7, 114.0],
    [114.0, 117.0, 112.0, 116.2],
    [116.2, 119.1, 114.2, 118.0],
    [118.0, 121.3, 116.0, 120.5],
    [120.5, 123.8, 118.3, 122.7],
    [122.7, 126.0, 120.4, 125.1],
    [125.1, 128.5, 122.6, 127.2],
    [127.2, 130.9, 124.7, 129.6],
    [129.6, 133.3, 127.2, 131.8],
    [131.8, 135.2, 129.4, 134.0],
    [134.0, 138.0, 131.0, 136.5],
    [136.5, 140.4, 133.2, 138.9]
]

Vec 내부에 Vec<f32>를 가지고 있는 구조이다.

파싱을 해보도록 하겠다.

#[derive(Serialize, Deserialize, Debug)]
struct CandleInfo {
    open_price: f32,
    high_price: f32,
    low_price: f32,
    close_price: f32,
}

impl CandleInfo {
    fn new(vec: &Vec<f32>) -> Self {
        CandleInfo {
            open_price: vec[0],
            high_price: vec[1],
            low_price: vec[2],
            close_price: vec[3],
        }
    }
}

CandleInfo 구조체를 생성했다. 필드를 4개를 선언하였고, Vec<f32>과 매칭된다.

#[derive(Serialize, Deserialize, Debug)]
struct Candles {
    candles: Vec<CandleInfo>,
}

impl Candles {
    fn new() -> Self {
        // 파일을 읽어주고, 읽은 string을 넘겨주면 된다. dsp_gstarcad202464
        let json_str =  std::fs::read_to_string("price.json").unwrap();
        let parsed: serde_json::Value = serde_json::from_str(json_str.as_str()).unwrap();

        let candles: Vec<CandleInfo> = parsed.as_array().unwrap().iter().map(|candle| {
            let vec: Vec<f32> = candle.as_array().unwrap().iter().map(|v| v.as_f64().unwrap() as f32).collect();
            let candle_info = CandleInfo::new(&vec);
            candle_info
        }).collect();

        Candles {
            candles: candles,
        }
    }
}
  1. json파일로부터 데이터를 String으로 읽어준다.

  2. Value로 데이터를 파싱한다.

  3. Value값이 array으로 변환하며 오류시 panic을 발생시킨다.

            let candles: Vec<CandleInfo> = parsed.as_array().unwrap().iter().map(|candle| {
                let vec: Vec<f32> = candle.as_array().unwrap().iter().map(|v| v.as_f64().unwrap() as f32).collect();
                let candle_info = CandleInfo::new(&vec);
                candle_info
            }).collect();
    

    map 내부에서 iter chain을 통해서 지연 실행되도록 로직을 작성하였다.
    같은 원리로 f32 동적 배열을 구해주었다.

https://docs.rs/serde_json/1.0.138/serde_json/enum.Value.html serde_jsonValue 문서를 보면 여러 메서드가 있다.
as_array의 시그니처는 다음과 같다.

pub fn as_array(&self) -> Option<&Vec<Value>>

Vec<Value>의 참조값을 반환한다. 내부 Value값도 알맞는 타입으로 파싱을 해주어야 한다.
위와 같은 경우 json 데이터가 모두 f32 타입이므로 as_f64로 캐스팅 후 다시 f32로 캐스팅 해주었다.

결론

매번 json을 파싱할때마다 헷갈렸고, 필드 키가 없는 배열 데이터를 파싱하는 방법을 알기위해 정리했다.
또 까먹으면 와서 봐야겠다.

0개의 댓글