2017-11-12 10 views
1

私は集計し、(平均、最大、最小などの)基本的な統計を実行する必要があるセンサーデータのストリームを受信して​​います。複数の値がありますが、センサーデータに不一致があり、値の一部が欠落している可能性があります。JSONオブジェクトの配列をプロパティで照合して、各オブジェクトのプロパティのベクトルを含む構造体にする方法はありますか?

luminosityまたはcolorの値がない場合は、Optionを使用する必要がありますが、これについては混乱しています。

これは私のセンサデータの一例である:

[ 
    { 
     "sensor": "left", 
     "luminosity": "50", 
     "color": "(255,0,0)" 
    }, 
    { 
     "sensor": "left", 
     "color": "#0f0" 
    }, 
    { 
     "sensor": "right", 
     "luminosity": "20" 
    }, 
    { 
     "sensor": "right", 
     "luminosity": "40", 
     "color": "(255,0,0)" 
    }, 
    { 
     "sensor": "left", 
     "luminosity": "30" 
    }, 
    { 
     "sensor": "top", 
     "luminosity": "10" 
    }, 
    { 
     "sensor": "right", 
     "color": "(0,0,0)" 
    } 
] 

各センサーのデータは、以下の構造体のインスタンスに格納されます。

struct Data { 
    pub luminosity: Vec<String>, 
    pub color: Vec<String>, 
} 

私は上記のJSONオブジェクトを反復処理したいですセンサーを正しい構造体インスタンス(「右」センサー構造体)に一致させ、各JSON観測の内容をベクトル(各構造体インスタンス内)にプッシュします。

各「観測」に対して、対応するセンサの構造体インスタンスの構造体の各ベクトルに対して1つのプッシュアクションが存在するように、欠損値を記録する必要があります。

+0

私たちは(HTTP [チャットでこの議論を続ける]してみましょう。 com/rooms/158788/discuss-greg-and-shepmaster)を参照してください。 – Greg

+0

これは[ユーザーのフォーラムに投稿されました](https://users.rust-lang.org/t/how-to-insert-the-contents-of-a-json-object-into-a-struct含有ベクトル/ 13830?u = shepmaster)。 – Shepmaster

答えて

2

何かこれはうまくいくはずです。 Serdeを使用して、各JSON配列要素をセンサーの各値に対して必要なセンサー名StringOption<String>のデータを持つヘルパー構造体に読み込みます。次に、これらの読み取り値をループし、キーがセンサー名であり、値が各センサー値のデータのベクトルであるマップに挿入します。


#[macro_use] 
extern crate serde_derive; 

extern crate serde; 
extern crate serde_json; 

use std::collections::BTreeMap as Map; 
use std::error::Error; 

#[derive(Debug, Default)] 
struct Data { 
    luminosity: Vec<Option<String>>, 
    color: Vec<Option<String>>, 
} 

fn main() { 
    let input = r##"[ 
         { 
         "sensor": "left", 
         "luminosity": "50", 
         "color": "(255,0,0)" 
         }, 
         { 
         "sensor": "left", 
         "color": "#0f0" 
         }, 
         { 
         "sensor": "right", 
         "luminosity": "20" 
         }, 
         { 
         "sensor": "right", 
         "luminosity": "40", 
         "color": "(255,0,0)" 
         }, 
         { 
         "sensor": "left", 
         "luminosity": "30" 
         }, 
         { 
         "sensor": "top", 
         "luminosity": "10" 
         }, 
         { 
         "sensor": "right", 
         "color": "(0,0,0)" 
         } 
        ]"##; 
    let m = read_sensor_data(input).unwrap(); 
    println!("{:#?}", m); 
} 

fn read_sensor_data(input: &str) -> Result<Map<String, Data>, Box<Error>> { 
    // Private helper struct that matches the format of the raw JSON 
    #[derive(Deserialize)] 
    struct RawReading { 
     sensor: String, 
     luminosity: Option<String>, 
     color: Option<String>, 
    } 

    // Deserialize the raw data 
    let raw_readings: Vec<RawReading> = serde_json::from_str(input)?; 

    // Loop over raw data and insert each reading into the right sensor's struct 
    let mut m = Map::new(); 
    for raw in raw_readings { 
     // Look up this sensor's Data struct 
     let sensor = m.entry(raw.sensor).or_insert_with(Data::default); 

     // One push for every vector in the struct, even for missing observations 
     sensor.luminosity.push(raw.luminosity); 
     sensor.color.push(raw.color); 
    } 
    Ok(m) 
} 
+0

完璧に動作します! – Greg

1

あなたはより多くのコードを犠牲にしてわずかより効率的にすることができます。これは、出力を生成

extern crate serde; 
#[macro_use] 
extern crate serde_derive; 
extern crate serde_json; 

use std::collections::HashMap; 
use std::fmt; 
use serde::de::{Deserialize, Deserializer, Visitor}; 

#[derive(Debug, Default)] 
struct Data { 
    luminosity: Vec<Option<String>>, 
    color: Vec<Option<String>>, 
} 

struct Wrapper(HashMap<String, Data>); 

impl<'de> Deserialize<'de> for Wrapper { 
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 
    where 
     D: Deserializer<'de>, 
    { 
     deserializer.deserialize_seq(WrapperVisitor) 
    } 
} 

struct WrapperVisitor; 

impl<'de> Visitor<'de> for WrapperVisitor { 
    type Value = Wrapper; 

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 
     formatter.write_str("a sequence of measurement objects") 
    } 

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> 
    where 
     A: serde::de::SeqAccess<'de>, 
    { 
     #[derive(Debug, Deserialize)] 
     struct DataPoint { 
      sensor: String, 
      luminosity: Option<String>, 
      color: Option<String>, 
     } 

     let mut all_data = HashMap::new(); 

     while let Some(data_point) = seq.next_element::<DataPoint>()? { 
      let data = all_data 
       .entry(data_point.sensor) 
       .or_insert_with(Data::default); 
      data.luminosity.push(data_point.luminosity); 
      data.color.push(data_point.color); 
     } 

     Ok(Wrapper(all_data)) 
    } 
} 

fn main() { 
    let input = r###" 
[ 
    { 
     "sensor": "left", 
     "luminosity": "50", 
     "color": "(255,0,0)" 
    }, 
    { 
     "sensor": "left", 
     "color": "#0f0" 
    }, 
    { 
     "sensor": "right", 
     "luminosity": "20" 
    }, 
    { 
     "sensor": "right", 
     "luminosity": "40", 
     "color": "(255,0,0)" 
    }, 
    { 
     "sensor": "left", 
     "luminosity": "30" 
    }, 
    { 
     "sensor": "top", 
     "luminosity": "10" 
    }, 
    { 
     "sensor": "right", 
     "color": "(0,0,0)" 
    } 
] 
"###; 

    let data = serde_json::from_str::<Wrapper>(input).expect("Nope"); 
    let data = data.0; 

    println!("{:#?}", data); 
} 

:あなたがあなた自身のVisitorの実装を作成する場合Vecをデシリアライズする必要はありません//chat.stackoverflow:

{ 
    "left": Data { 
     luminosity: [ 
      Some("50"), 
      None, 
      Some("30") 
     ], 
     color: [ 
      Some("(255,0,0)"), 
      Some("#0f0"), 
      None 
     ] 
    }, 
    "right": Data { 
     luminosity: [ 
      Some("20"), 
      Some("40"), 
      None 
     ], 
     color: [ 
      None, 
      Some("(255,0,0)"), 
      Some("(0,0,0)") 
     ] 
    }, 
    "top": Data { 
     luminosity: [ 
      Some("10") 
     ], 
     color: [ 
      None 
     ] 
    } 
} 
関連する問題