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

Rust proptest如何根据Schema生成符合规范的JSON对象策略

基于proptest生成符合OpenAPI Schema的嵌套JSON

需求

  • 基于Rust proptest库生成遵循OpenAPI Schema约束的JSON,不生成无约束随机JSON
  • JSON对象的键为Schema预定义的固定值,无需随机生成,仅递归调用对应策略生成键对应的值
  • 最终返回策略类型为BoxedStrategy<serde_json::Value>,支持对象任意层级嵌套
  • 已完成原始类型策略实现,仅对象生成逻辑存在问题

原有错误原因

之前的实现直接将值生成策略插入serde_json::Map,而非策略运行后生成的JSON值,导致类型不匹配:

fn generate_json_object(object: &ObjectType) -> BoxedStrategy<serde_json::Value> {
    let mut json_object = serde_json::Map::with_capacity(object.properties.len());
    for (name, schema) in &object.properties {
        let schema_kind = &schema.to_item_ref().schema_kind;
        // 错误:此处插入的是BoxedStrategy类型,不是serde_json::Value
        json_object.insert(name.clone(), schema_kind_to_json(schema_kind));
    }
    Just(serde_json::Value::Object(json_object)).boxed()
}

尝试的hash_map+固定键Just、prop_filter_map方案均无法优雅支持嵌套组合。

正确实现

核心逻辑:先为每个固定键匹配对应的值生成策略,将所有属性策略组合为列表策略,最终映射组装为serde_json::Value::Object,无需使用HashMapStrategy。

use proptest::prelude::*;
use proptest::collection;
use serde_json::{Value, Map};

fn generate_json_object(object: &ObjectType) -> BoxedStrategy<Value> {
    // 收集每个属性对应的(键, 值)生成策略
    let mut prop_strategies = Vec::with_capacity(object.properties.len());
    for (prop_name, schema) in &object.properties {
        let schema_kind = &schema.to_item_ref().schema_kind;
        let value_strat = schema_kind_to_json(schema_kind);
        // 固定键用Just包装,和值策略组合为单个键值对的生成策略
        prop_strategies.push(
            (Just(prop_name.clone()), value_strat)
                .prop_map(|(key, val)| (key, val))
        );
    }

    // 组合所有属性策略,生成固定长度的键值对列表
    let all_props_strat = collection::vec(prop_strategies, object.properties.len());

    // 将键值对列表组装为serde_json对象,包装为目标类型
    all_props_strat
        .prop_map(|pairs| {
            let mut map = Map::with_capacity(pairs.len());
            for (k, v) in pairs {
                map.insert(k, v);
            }
            Value::Object(map)
        })
        .boxed()
}

实现说明

  • 固定键场景不需要使用hash_map策略:直接用Just持有预定义键名,和对应值策略配对即可,省去键生成、过滤的冗余逻辑
  • 天然支持嵌套:如果属性对应Schema为对象类型,schema_kind_to_json会递归调用当前函数返回嵌套对象策略,proptest自动处理策略嵌套
  • 类型匹配:所有策略最终生成的都是serde_json::Value类型,不存在将策略本身当作值插入的类型错误
  • 扩展支持可选属性:只需对非必填属性的值策略用prop::option::of包装,最终在prop_map阶段过滤掉值为None的键值对即可适配OpenAPI的required约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:27:26