use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubjectInfo {
#[serde(rename = "subjectName")]
pub subject_name: String,
#[serde(rename = "dateOfBirth")]
pub date_of_birth: Option<String>,
pub sex: Option<String>,
#[serde(rename = "countryCode")]
pub country_code: Option<String>,
#[serde(rename = "countryName")]
pub country_name: Option<String>,
pub state: Option<String>,
pub city: Option<String>,
pub attributes: Option<Vec<serde_json::Value>>,
#[serde(rename = "experimentsCount")]
pub experiments_count: Option<u32>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct DemographicAttribute {
pub name: String,
pub value: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubjectRequest {
pub subject_name: String,
pub date_of_birth: Option<String>,
pub sex: Option<String>,
pub country_code: Option<String>,
pub state: Option<String>,
pub city: Option<String>,
pub attributes: Option<Vec<serde_json::Value>>,
}
impl SubjectRequest {
pub fn new(subject_name: impl Into<String>) -> Self {
Self {
subject_name: subject_name.into(),
date_of_birth: None,
sex: None,
country_code: None,
state: None,
city: None,
attributes: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuerySubjectsRequest {
pub query: serde_json::Value,
pub order_by: serde_json::Value,
pub limit: Option<u32>,
pub offset: Option<u32>,
}
impl Default for QuerySubjectsRequest {
fn default() -> Self {
Self {
query: serde_json::json!({}),
order_by: serde_json::json!([]),
limit: None,
offset: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_subject_info() {
let json = r#"{
"subjectName": "subject01",
"dateOfBirth": "1990-01-15",
"sex": "M",
"countryCode": "US",
"countryName": "United States",
"state": "California",
"city": "San Francisco",
"experimentsCount": 5
}"#;
let info: SubjectInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.subject_name, "subject01");
assert_eq!(info.date_of_birth.as_deref(), Some("1990-01-15"));
assert_eq!(info.sex.as_deref(), Some("M"));
assert_eq!(info.country_code.as_deref(), Some("US"));
assert_eq!(info.experiments_count, Some(5));
assert!(info.attributes.is_none());
}
#[test]
fn test_deserialize_subject_info_minimal() {
let json = r#"{"subjectName": "subject02"}"#;
let info: SubjectInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.subject_name, "subject02");
assert!(info.date_of_birth.is_none());
assert!(info.sex.is_none());
assert!(info.experiments_count.is_none());
}
#[test]
fn test_deserialize_demographic_attribute() {
let json = r#"[
{"name": "sex", "value": ["M", "F", "U"]},
{"name": "country", "value": ["US", "GB", "DE"]}
]"#;
let attrs: Vec<DemographicAttribute> = serde_json::from_str(json).unwrap();
assert_eq!(attrs.len(), 2);
assert_eq!(attrs[0].name, "sex");
assert_eq!(attrs[0].value, vec!["M", "F", "U"]);
assert_eq!(attrs[1].name, "country");
}
}