serde_helpers.rs

 1use schemars::{
 2    SchemaGenerator,
 3    schema::{ArrayValidation, InstanceType, Schema, SchemaObject, SingleOrVec, StringValidation},
 4};
 5use serde::de::{self, Deserializer, Visitor};
 6use std::fmt;
 7
 8/// Generates a JSON schema for a non-empty string array.
 9pub fn non_empty_string_vec_json_schema(_: &mut SchemaGenerator) -> Schema {
10    Schema::Object(SchemaObject {
11        instance_type: Some(InstanceType::Array.into()),
12        array: Some(Box::new(ArrayValidation {
13            unique_items: Some(true),
14            items: Some(SingleOrVec::Single(Box::new(Schema::Object(
15                SchemaObject {
16                    instance_type: Some(InstanceType::String.into()),
17                    string: Some(Box::new(StringValidation {
18                        min_length: Some(1), // Ensures string in the array is non-empty
19                        ..Default::default()
20                    })),
21                    ..Default::default()
22                },
23            )))),
24            ..Default::default()
25        })),
26        format: Some("vec-of-non-empty-strings".to_string()), // Use a custom format keyword
27        ..Default::default()
28    })
29}
30
31/// Deserializes a non-empty string array.
32pub fn non_empty_string_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
33where
34    D: Deserializer<'de>,
35{
36    struct NonEmptyStringVecVisitor;
37
38    impl<'de> Visitor<'de> for NonEmptyStringVecVisitor {
39        type Value = Vec<String>;
40
41        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
42            formatter.write_str("a list of non-empty strings")
43        }
44
45        fn visit_seq<V>(self, mut seq: V) -> Result<Vec<String>, V::Error>
46        where
47            V: de::SeqAccess<'de>,
48        {
49            let mut vec = Vec::new();
50            while let Some(value) = seq.next_element::<String>()? {
51                if value.is_empty() {
52                    return Err(de::Error::invalid_value(
53                        de::Unexpected::Str(&value),
54                        &"a non-empty string",
55                    ));
56                }
57                vec.push(value);
58            }
59            Ok(vec)
60        }
61    }
62
63    deserializer.deserialize_seq(NonEmptyStringVecVisitor)
64}