Почему этот вопрос существует?
Я пишу rabbithole-rs , который представляет собой реализацию JSON: API, основанную на Rust. Но при разработке функций сортировки / разбивки на страницы, я сталкиваюсь с большой проблемой при разработке полей attribute
.
Intro JSON: API soring / pagination кратко
Есть поля attributes
в JSON: объект API resource
, который является HashMap<String, serde_json::Value>
или HashMap<String, Box<Any>>
, где ключом является имя атрибута , а значением является значение атрибута.
И Vec<Resource>
У объекта есть метод sort(attribute_name: &str)
, который может сортировать группу Resource
на основе одного из атрибутов.
Краткое описание Resource
pub struct Resource {
pub ty: String, // The type of `Resource`, `sort` method can only effect on the same type of resources
pub id: String, // Every `Resource` has an unique id
pub attr1: dyn Ord + Serialize + Deserialize,
... <more attrs>
}
Где:
- Каждый
attr
должен реализовывать как минимум три черты: Ord
для сравнения Serialize
для преобразования в serde_json::Value
Deserialize
для преобразования из serde_json::Value
В чем проблема?
При получении Resource
мне нужно извлечь всеattribute
полей и поместите их в HashMap
, например: HashMap<String, serde_json::Value>
или HashMap<String, Box<Any>>
. Но оба они теряют информацию о характеристиках атрибутов, поэтому я не могу сравнить два элемента атрибута с одинаковыми именами.
Краткая демонстрация, пожалуйста!
Конечно! Вот, пожалуйста!
#[macro_use]
extern crate serde_derive;
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::collections::HashMap;
/// This is a struct field
#[derive(Debug, Serialize, Deserialize, Ord, PartialOrd, PartialEq, Eq)]
pub struct Name {
pub first_name: String,
pub last_name: String,
}
/// Resource object
#[derive(Debug, Serialize, Deserialize, Ord, PartialOrd, PartialEq, Eq)]
pub struct Resource {
pub ty: String,
pub id: String,
pub age: i32, // attr 1
pub name: Name, // another attr
}
fn main() {
let item1 = Resource {
ty: "human".into(),
id: "id1".to_string(),
age: 1,
name: Name {
first_name: "first1".to_string(),
last_name: "last1".to_string(),
},
};
// **This is the first attributes HashMap**
let mut map_item1: HashMap<&str, (&str, Box<dyn Any>)> = Default::default();
map_item1.insert("age", ("i32", Box::new(item1.age)));
map_item1.insert("name", ("Name", Box::new(item1.name)));
let item2 = Resource {
ty: "human".into(),
id: "id2".to_string(),
age: 2,
name: Name {
first_name: "first2".to_string(),
last_name: "last2".to_string(),
},
};
// **This is the second attributes HashMap**
let mut map_item2: HashMap<&str, (&str, Box<dyn Any>)> = Default::default();
map_item2.insert("age", ("i32", Box::new(item2.age)));
map_item2.insert("name", ("Name", Box::new(item2.name)));
// TODO: NEED TO BE IMPLEMENTED
for k in map_item1.keys() {
println!(
"key: {key}, item1.{key} < item2.{key}? {res}",
key = k,
res = map_item1.get(k).unwrap().1.cmp(map_item2.get(k).unwrap().1)
)
}
}