serde_json
으로 데이터 파싱하는것을 정리하겠다.
특히 json파일에서 필드값이 없는 경우를 serde_json
의 Value
를 활용하여 파싱하는법을 알아보겠다.
아래 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,
}
}
}
json
파일로부터 데이터를 String
으로 읽어준다.
Value
로 데이터를 파싱한다.
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_json
의 Value
문서를 보면 여러 메서드가 있다.
as_array
의 시그니처는 다음과 같다.
pub fn as_array(&self) -> Option<&Vec<Value>>
Vec<Value>
의 참조값을 반환한다. 내부 Value값도 알맞는 타입으로 파싱을 해주어야 한다.
위와 같은 경우 json 데이터가 모두 f32 타입이므로 as_f64
로 캐스팅 후 다시 f32
로 캐스팅 해주었다.
매번 json을 파싱할때마다 헷갈렸고, 필드 키가 없는 배열 데이터를 파싱하는 방법을 알기위해 정리했다.
또 까먹으면 와서 봐야겠다.