Reputation: 601
I'd like to create a JSON strategy using rust proptest library. However, I do not want to create an arbitrary JSON. I'd like to create it according to a schema (more specifically, OpenAPI schema). This means that keys of the JSON are known and I do not want to create them using any strategy, but I'd like to create the values using the strategy (pretty-much recursively).
I already implemented the strategy for primitive types, but I do not how to create a JSON object strategy.
I would like the strategy to have the type BoxedStratedy<serde_json::Value>
or be able to map the strategy to this type because the JSON objects can contain other objects, and thus I need to be able to compose the strategies.
I found a HashMapStrategy
strategy, however, it can be only created by a hash_map
function that takes two strategies - one for generating keys and one for values. I thought that I could use Just
strategy for the keys, but it did not lead anywhere. Maybe prop_filter_map
could be used.
Here is the code. There are tests too. One is passing because it tests only primitive type and the other is failing since I did not find a way to implement generate_json_object
function.
I tried this but the types do not match. Instead of a strategy of map from string
to JSON value, it is a strategy of a map from string
to BoxedStrategy
.
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;
json_object.insert(name.clone(), schema_kind_to_json(schema_kind));
}
Just(serde_json::Value::Object(json_object)).boxed()
}
Upvotes: 0
Views: 468
Reputation: 601
One can create a vector of strategies, which implements a Strategy
trait and can be boxed. So to create a serde_json::Value::Object
, we create a vector of tuples. The first element will be a Just
of key and the second element will be a boxed strategy of value. The boxed strategy of value can be created by schema_kind_to_json
function. After we have a vector of tuples which implement a Strategy
, we can use .prop_map
to transform it to a serde_json::Value::Object
.
fn generate_json_object(object: &ObjectType) -> BoxedStrategy<serde_json::Value> {
let mut vec = Vec::with_capacity(object.properties.len());
for (name, schema) in &object.properties {
let schema_kind = &schema.to_item_ref().schema_kind;
vec.push((Just(name.clone()), schema_kind_to_json(schema_kind)));
}
vec.prop_map(|vec| serde_json::Value::Object(serde_json::Map::from_iter(vec)))
.boxed()
}
Upvotes: 0