如何在编译时确保类型将序列化为 JSON 数组?

How to ensure at compile time that a type will serialize into a JSON array?

我有一个特征,可以用作 Rails' ActiveJob 的接口;我希望我的 Rust 后端触发由 Rails API:

处理的作业
trait BackgroundJob {
    type Args: Serialize;
    const QUEUE: &'static str;
    const CLASS: JobClass;

    fn payload(self) -> Self::Args;
}

特征的示例实现:

impl BackgroundJob for MyJob {
    type Args = (String,);
    const QUEUE: &'static str = "my_queue";
    const CLASS: JobClass = JobClass::Job1;

    fn payload(self) -> Self::Args {
        (self.payload,)
    }
}

playground

在我的应用程序中,代码有点复杂(具体来说,我有一个 Actix actor 而不是 BackgroundJob 上的通用函数),但想法是一样的。

这段代码工作正常,但我必须确保 BackgroundJob 的所有实现都将作为 Args 类型参数,将序列化为 JSON 数组(到与积极的工作一起工作)。

我想做的是编译时保证 Args 将序列化为一个数组。这可能吗?

我试图解决来自 Serde 的 SerializeTupleSerializeSeq 特征,但没有成功。

我很确定答案是 "no, there's nothing native to Serde to do this"。没有符合此特定需求的特征。

您可以创建自己的 marker trait 并要求它存在,但它不会被任何东西自动实现;您必须为任何有效类型手动实现它。我猜这不是你想要的:

trait SerializeToJsonArray {}

impl<T> SerializeToJsonArray for Vec<T> {}
impl<T> SerializeToJsonArray for [T] {}
impl<A> SerializeToJsonArray for (A, ) {}
impl<A, B> SerializeToJsonArray for (A, B, ) {}
impl<A, B, C> SerializeToJsonArray for (A, B, C, ) {}
// etc.

trait BackgroundJob {
    type Args: Serialize + SerializeToJsonArray;
}

这也很容易破坏 — 对于 序列化为数组的类型,您可以轻松实现 SerializeToJsonArray。同样,Serde 不知道这个特性,您仍然需要在序列化时处理非数组。