You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Schemars生成SignedDecimal字符串形式的JSON Schema而非结构体字段

解决方案:让SignedDecimal序列化为字符串并生成对应JSON Schema

步骤1:为SignedDecimal实现自定义序列化/反序列化逻辑

你已经具备String转换的实现,现在需要替换默认的序列化行为,让SignedDecimal直接输出为字符串而非嵌套结构体形式:

use serde::{Serialize, Deserializer, Serializer};
use schemars::{JsonSchema, schema::Schema};

// 保留你的String转换逻辑(示例)
impl From<SignedDecimal> for String {
    fn from(val: SignedDecimal) -> Self {
        let sign = if val.sign { "" } else { "-" };
        format!("{}{}", sign, val.value)
    }
}

impl TryFrom<&str> for SignedDecimal {
    type Error = /* 替换为你的错误类型 */;
    fn try_from(s: &str) -> Result<Self, Self::Error> {
        // 实现你的字符串解析逻辑
        Ok(SignedDecimal {
            sign: !s.starts_with('-'),
            value: /* 解析得到的Decimal256实例 */,
        })
    }
}

// 自定义序列化
impl Serialize for SignedDecimal {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let str_val: String = self.into();
        serializer.serialize_str(&str_val)
    }
}

// 自定义反序列化
impl<'de> Deserialize<'de> for SignedDecimal {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let str_val = String::deserialize(deserializer)?;
        SignedDecimal::try_from(str_val.as_str()).map_err(serde::de::Error::custom)
    }
}

步骤2:为SignedDecimal实现自定义JSON Schema生成逻辑

之前使用#[schemars(schema_with = "String")]无效,是因为schema_with需要传入生成Schema的函数而非类型名。需要定义专属函数并指定:

// 生成字符串类型Schema的函数
fn signed_decimal_schema(_gen: &mut schemars::gen::SchemaGenerator) -> Schema {
    schemars::schema::SchemaObject {
        instance_type: Some(schemars::schema::InstanceType::String.into()),
        ..Default::default()
    }
    .into()
}

// 修改SignedDecimal的宏注解,去掉默认的Serialize/Deserialize derive(改用自定义实现)
#[derive(Clone, Copy, Debug, JsonSchema)]
#[schemars(schema_with = "signed_decimal_schema")]
pub struct SignedDecimal {
    value: Decimal256,
    sign: bool,
}

步骤3:验证效果

此时Position结构体无需任何修改,序列化后会生成你期望的格式:

{
    "x": "1.5",
    "y": "1.5"
}

同时生成的JSON Schema中,x、y字段的类型会被标记为字符串,完全符合需求。

关键说明

  • 移除SignedDecimal默认的Serialize/Deserialize derive,改用自定义实现,直接输出字符串而非嵌套结构体。
  • schema_with参数必须传入返回Schema类型的函数,而非类型名,这是之前写法无效的核心原因。
  • 全程无需修改Position结构体,仅调整SignedDecimal的实现与宏注解即可达成目标。

内容的提问来源于stack exchange,提问作者ewoolsey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:10:29