Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cell::RefCell;
- use std::rc::Rc;
- use serde::de::{self, MapAccess, SeqAccess, Visitor};
- use serde::{Deserialize, Deserializer, Serialize};
- #[derive(Debug, Serialize)]
- struct Response<'a> {
- categories: Vec<Category<'a>>,
- }
- type RefItem<'a> = Rc<RefCell<Item<'a>>>;
- #[derive(Debug, Serialize)]
- struct Category<'a> {
- id: &'a str,
- name: &'a str,
- items: Vec<RefItem<'a>>,
- }
- #[derive(Debug, Deserialize, Serialize)]
- struct Item<'a> {
- id: &'a str,
- name: &'a str,
- }
- impl<'de> Deserialize<'de> for Response<'de> {
- fn deserialize<D>(deserializer: D) -> Result<Response<'de>, D::Error>
- where
- D: Deserializer<'de>,
- {
- use std::collections::BTreeMap as Map;
- #[derive(Deserialize)]
- #[serde(field_identifier, rename_all = "lowercase")]
- enum Field {
- Categories,
- Items,
- };
- #[derive(Debug, Deserialize)]
- struct RawCategory<'a> {
- id: &'a str,
- name: &'a str,
- item_ids: Vec<&'a str>,
- }
- // struct ItemsMap<'a>(Vec<RefItem<'a>>);
- struct ItemsMap<'a>(Map<&'a str, RefItem<'a>>);
- impl<'de> Deserialize<'de> for ItemsMap<'de> {
- fn deserialize<D>(deserializer: D) -> Result<ItemsMap<'de>, D::Error>
- where
- D: Deserializer<'de>,
- {
- struct ItemsMapVisitor;
- impl<'de> Visitor<'de> for ItemsMapVisitor {
- type Value = ItemsMap<'de>;
- fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
- formatter.write_str("struct Item")
- }
- fn visit_seq<V>(self, mut seq: V) -> Result<ItemsMap<'de>, V::Error>
- where
- V: SeqAccess<'de>,
- {
- let mut map = Map::new();
- while let Some(item) = seq.next_element::<Item<'de>>()? {
- map.insert(item.id, Rc::new(RefCell::new(item)));
- }
- Ok(ItemsMap(map))
- // let mut vec = Vec::new();
- // while let Some(item) = seq.next_element::<Item<'de>>()? {
- // vec.push(Rc::new(RefCell::new(item)));
- // }
- // Ok(ItemsMap(vec))
- }
- }
- deserializer.deserialize_seq(ItemsMapVisitor)
- }
- }
- struct ResponseVisitor;
- impl<'de> Visitor<'de> for ResponseVisitor {
- type Value = Response<'de>;
- fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
- formatter.write_str("struct Response")
- }
- fn visit_map<V>(self, mut map: V) -> Result<Response<'de>, V::Error>
- where
- V: MapAccess<'de>,
- {
- let mut raw_categories: Option<Vec<RawCategory<'de>>> = None;
- let mut items_map: Option<ItemsMap<'de>> = None;
- while let Some(key) = map.next_key()? {
- match key {
- Field::Categories => {
- if raw_categories.is_some() {
- return Err(de::Error::duplicate_field("categories"));
- }
- raw_categories = Some(map.next_value()?);
- }
- Field::Items => {
- if items_map.is_some() {
- return Err(de::Error::duplicate_field("items"));
- }
- items_map = Some(map.next_value()?);
- }
- }
- }
- let raw_categories =
- raw_categories.ok_or_else(|| de::Error::missing_field("categories"))?;
- let items_map = items_map.ok_or_else(|| de::Error::missing_field("items"))?;
- let categories: Vec<_> = raw_categories
- .iter()
- .map(|category| {
- let items: Vec<_> = category
- .item_ids
- .iter()
- .map(|id| {
- items_map
- .0
- .get(id)
- .map(|rc| rc.clone())
- .ok_or_else(|| de::Error::custom("can't find item"))
- })
- // .map(|id| {
- // items_map
- // .0
- // .iter()
- // .find(|item| &item.borrow().id == id)
- // .map(|rc| rc.clone())
- // .ok_or_else(|| de::Error::custom("can't find item"))
- // })
- .collect::<Result<Vec<_>, _>>()?;
- Ok(Category {
- id: category.id,
- name: category.name,
- items,
- })
- })
- .collect::<Result<Vec<_>, _>>()?;
- Ok(Response { categories })
- }
- }
- deserializer.deserialize_struct("Response", &["categories", "items"], ResponseVisitor)
- }
- }
- fn main() {
- let json = r##"{
- "items": [{
- "id": "1",
- "name": "1"
- }, {
- "id": "2",
- "name": "2"
- }, {
- "id": "3",
- "name": "3"
- }],
- "categories": [{
- "id": "1",
- "name": "1",
- "item_ids": []
- }, {
- "id": "2",
- "name": "2",
- "item_ids": ["1", "2"]
- }, {
- "id": "3",
- "name": "3",
- "item_ids": ["2", "3"]
- }]
- }"##;
- let deserialized: Response = serde_json::from_str(&json).unwrap();
- println!("{:#?}", deserialized);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement