Savior

Serde: deserialize into a Vec of Rc<RefCell<_>>

Feb 16th, 2020
615
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. use std::cell::RefCell;
  2. use std::rc::Rc;
  3.  
  4. use serde::de::{self, MapAccess, SeqAccess, Visitor};
  5. use serde::{Deserialize, Deserializer, Serialize};
  6.  
  7. #[derive(Debug, Serialize)]
  8. struct Response<'a> {
  9.    categories: Vec<Category<'a>>,
  10. }
  11.  
  12. type RefItem<'a> = Rc<RefCell<Item<'a>>>;
  13.  
  14. #[derive(Debug, Serialize)]
  15. struct Category<'a> {
  16.    id: &'a str,
  17.     name: &'a str,
  18.    items: Vec<RefItem<'a>>,
  19. }
  20.  
  21. #[derive(Debug, Deserialize, Serialize)]
  22. struct Item<'a> {
  23.    id: &'a str,
  24.     name: &'a str,
  25. }
  26.  
  27. impl<'de> Deserialize<'de> for Response<'de> {
  28.     fn deserialize<D>(deserializer: D) -> Result<Response<'de>, D::Error>
  29.    where
  30.        D: Deserializer<'de>,
  31.     {
  32.         use std::collections::BTreeMap as Map;
  33.  
  34.         #[derive(Deserialize)]
  35.         #[serde(field_identifier, rename_all = "lowercase")]
  36.         enum Field {
  37.             Categories,
  38.             Items,
  39.         };
  40.  
  41.         #[derive(Debug, Deserialize)]
  42.         struct RawCategory<'a> {
  43.            id: &'a str,
  44.             name: &'a str,
  45.            item_ids: Vec<&'a str>,
  46.         }
  47.  
  48.         // struct ItemsMap<'a>(Vec<RefItem<'a>>);
  49.         struct ItemsMap<'a>(Map<&'a str, RefItem<'a>>);
  50.  
  51.        impl<'de> Deserialize<'de> for ItemsMap<'de> {
  52.             fn deserialize<D>(deserializer: D) -> Result<ItemsMap<'de>, D::Error>
  53.            where
  54.                D: Deserializer<'de>,
  55.             {
  56.                 struct ItemsMapVisitor;
  57.  
  58.                 impl<'de> Visitor<'de> for ItemsMapVisitor {
  59.                     type Value = ItemsMap<'de>;
  60.  
  61.                    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
  62.                        formatter.write_str("struct Item")
  63.                    }
  64.  
  65.                    fn visit_seq<V>(self, mut seq: V) -> Result<ItemsMap<'de>, V::Error>
  66.                     where
  67.                         V: SeqAccess<'de>,
  68.                    {
  69.                        let mut map = Map::new();
  70.                        while let Some(item) = seq.next_element::<Item<'de>>()? {
  71.                             map.insert(item.id, Rc::new(RefCell::new(item)));
  72.                         }
  73.  
  74.                         Ok(ItemsMap(map))
  75.  
  76.                         // let mut vec = Vec::new();
  77.                         // while let Some(item) = seq.next_element::<Item<'de>>()? {
  78.                         //     vec.push(Rc::new(RefCell::new(item)));
  79.                         // }
  80.  
  81.                         // Ok(ItemsMap(vec))
  82.                     }
  83.                 }
  84.  
  85.                 deserializer.deserialize_seq(ItemsMapVisitor)
  86.             }
  87.         }
  88.  
  89.         struct ResponseVisitor;
  90.  
  91.         impl<'de> Visitor<'de> for ResponseVisitor {
  92.             type Value = Response<'de>;
  93.  
  94.            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
  95.                formatter.write_str("struct Response")
  96.            }
  97.  
  98.            fn visit_map<V>(self, mut map: V) -> Result<Response<'de>, V::Error>
  99.             where
  100.                 V: MapAccess<'de>,
  101.            {
  102.                let mut raw_categories: Option<Vec<RawCategory<'de>>> = None;
  103.                 let mut items_map: Option<ItemsMap<'de>> = None;
  104.  
  105.                while let Some(key) = map.next_key()? {
  106.                    match key {
  107.                        Field::Categories => {
  108.                            if raw_categories.is_some() {
  109.                                return Err(de::Error::duplicate_field("categories"));
  110.                            }
  111.                            raw_categories = Some(map.next_value()?);
  112.                        }
  113.                        Field::Items => {
  114.                            if items_map.is_some() {
  115.                                return Err(de::Error::duplicate_field("items"));
  116.                            }
  117.                            items_map = Some(map.next_value()?);
  118.                        }
  119.                    }
  120.                }
  121.                let raw_categories =
  122.                    raw_categories.ok_or_else(|| de::Error::missing_field("categories"))?;
  123.                let items_map = items_map.ok_or_else(|| de::Error::missing_field("items"))?;
  124.  
  125.                let categories: Vec<_> = raw_categories
  126.                    .iter()
  127.                    .map(|category| {
  128.                        let items: Vec<_> = category
  129.                            .item_ids
  130.                            .iter()
  131.                            .map(|id| {
  132.                                items_map
  133.                                    .0
  134.                                    .get(id)
  135.                                    .map(|rc| rc.clone())
  136.                                    .ok_or_else(|| de::Error::custom("can't find item"))
  137.                            })
  138.                            // .map(|id| {
  139.                            //     items_map
  140.                            //         .0
  141.                            //         .iter()
  142.                            //         .find(|item| &item.borrow().id == id)
  143.                            //         .map(|rc| rc.clone())
  144.                            //         .ok_or_else(|| de::Error::custom("can't find item"))
  145.                            // })
  146.                            .collect::<Result<Vec<_>, _>>()?;
  147.  
  148.                        Ok(Category {
  149.                            id: category.id,
  150.                            name: category.name,
  151.                            items,
  152.                        })
  153.                    })
  154.                    .collect::<Result<Vec<_>, _>>()?;
  155.  
  156.                Ok(Response { categories })
  157.            }
  158.        }
  159.  
  160.        deserializer.deserialize_struct("Response", &["categories", "items"], ResponseVisitor)
  161.    }
  162. }
  163.  
  164. fn main() {
  165.    let json = r##"{
  166.    "items": [{
  167.        "id": "1",
  168.        "name": "1"
  169.    }, {
  170.        "id": "2",
  171.        "name": "2"
  172.    }, {
  173.        "id": "3",
  174.        "name": "3"
  175.    }],
  176.    "categories": [{
  177.        "id": "1",
  178.        "name": "1",
  179.        "item_ids": []
  180.    }, {
  181.        "id": "2",
  182.        "name": "2",
  183.        "item_ids": ["1", "2"]
  184.    }, {
  185.        "id": "3",
  186.        "name": "3",
  187.        "item_ids": ["2", "3"]
  188.    }]
  189. }"##;
  190.    
  191.    let deserialized: Response = serde_json::from_str(&json).unwrap();
  192.    println!("{:#?}", deserialized);
  193. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×