Closed dawn-stripe closed 3 years ago
@dawn-stripe I'm looking into this.
@dawn-stripe as you have not defined any properties in the case of metadata
being an object, the schemaFaker
is not able to generate data. Do you want a parameter even if the there are no properties defined for the object? Currently only the first element from the anyOf
array is considered for schema resolution and in this case as the object doesn't have any properties, the parameter isn't added.
Thank you for that explanation @pcgamer1. We don't have any properties defined since the metadata keys are all used defined.
Do you want a parameter even if the there are no properties defined for the object? Yes, we'd still like for the parameter to appear as an optional parameter in the request.
metadata[key]
would be a perfect placeholder.
I don't mind adding something to the spec to help the faker generate data, but I've not been having luck trying to figure out what I would add that would get the parameter added, for example this doesn't work (I also experimented with moving the enum to be the first element and adding a placeholder value to the enum itself.
"metadata": {
"anyOf": [
{
"foo": {
"type": "string",
"maxLength": 5000,
"description": "example metadata key, replace with your key and value"
},
"type": "string"
},
{
"enum": [
""
],
"type": "string"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
],
"description": "Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to `metadata`."
},
@dawn-stripe Happy to be able to help. I tried with the above spec, there is a parameter being added for the metadata
string i.e. the first element of the anyOf
array. Is this not the expected result for you? Thanks.
hi @pcgamer1 : hmmm, I am not seeing it in resulting collection JSON. I wondered if it was b/c I hadn't added it to the schema, but even when I fixed that I still did not see that first foo
element appear. Ideas?
Here's my post body:
"description"':...",
"operationId": "PostCoupons",
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"encoding": {
"applies_to": {
"explode": true,
"style": "deepObject"
},
"expand": {
"explode": true,
"style": "deepObject"
},
"metadata": {
"explode": true,
"style": "deepObject"
}
},
"schema": {
"additionalProperties": false,
"properties": {
"amount_off": {
"description": "A positive integer representing the amount to subtract from an invoice total (required if `percent_off` is not passed).",
"type": "integer"
},
"applies_to": {
"description": "A hash containing directions for what this Coupon will apply discounts to.",
"properties": {
"products": {
"items": {
"maxLength": 5000,
"type": "string"
},
"type": "array"
}
},
"required": [
"products"
],
"title": "applies_to_params",
"type": "object"
},
"currency": {
"description": "Three-letter [ISO code for the currency](https://stripe.com/docs/currencies) of the `amount_off` parameter (required if `amount_off` is passed).",
"type": "string"
},
"duration": {
"description": "Specifies how long the discount will be in effect. Can be `forever`, `once`, or `repeating`.",
"enum": [
"forever",
"once",
"repeating"
],
"type": "string"
},
"duration_in_months": {
"description": "Required only if `duration` is `repeating`, in which case it must be a positive integer that specifies the number of months the discount will be in effect.",
"type": "integer"
},
"expand": {
"description": "Specifies which fields in the response should be expanded.",
"items": {
"maxLength": 5000,
"type": "string"
},
"type": "array"
},
"id": {
"description": "Unique string of your choice that will be used to identify this coupon when applying it to a customer. If you don't want to specify a particular code, you can leave the ID blank and we'll generate a random code for you.",
"maxLength": 5000,
"type": "string"
},
"max_redemptions": {
"description": "A positive integer specifying the number of times the coupon can be redeemed before it's no longer valid. For example, you might have a 50% off coupon that the first 20 readers of your blog can use.",
"type": "integer"
},
"metadata": {
"anyOf": [
{
"foo": {
"type": "string",
"maxLength": 5000,
"description": "example metadata key, replace with your key and value"
},
"type": "string"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"enum": [
""
],
"type": "string"
}
],
"description": "Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to `metadata`."
},
"name": {
"description": "Name of the coupon displayed to customers on, for instance invoices, or receipts. By default the `id` is shown if `name` is not set.",
"maxLength": 40,
"type": "string"
},
"percent_off": {
"description": "A positive float larger than 0, and smaller or equal to 100, that represents the discount the coupon will apply (required if `amount_off` is not passed).",
"type": "number"
},
"redeem_by": {
"description": "Unix timestamp specifying the last time at which the coupon can be redeemed. After the redeem_by date, the coupon can no longer be applied to new customers.",
"format": "unix-time",
"type": "integer"
}
},
"required": [
"duration"
],
"type": "object"
}
}
},
"required": true
},
And the resulting output:
"id": "9ceba8f4-7f0f-4e80-8446-80212fa47ea8",
"name": "Create a coupon",
"request": {
"name": "Create a coupon",
"description": {
"content": "..",
"type": "text/plain"
},
"url": {
"path": [
"v1",
"coupons"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": []
},
"header": [
{
"key": "Content-Type",
"value": "application/x-www-form-urlencoded"
}
],
"method": "POST",
"auth": null,
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"disabled": false,
"key": "duration",
"value": "<string>",
"description": "(Required) Specifies how long the discount will be in effect. Can be `forever`, `once`, or `repeating`."
},
{
"disabled": true,
"key": "amount_off",
"value": "<integer>",
"description": "A positive integer representing the amount to subtract from an invoice total (required if `percent_off` is not passed)."
},
{
"disabled": true,
"key": "applies_to[products]",
"value": "[\"<string>\",\"<string>\"]",
"description": "A hash containing directions for what this Coupon will apply discounts to."
},
{
"disabled": true,
"key": "currency",
"value": "<string>",
"description": "Three-letter [ISO code for the currency](https://stripe.com/docs/currencies) of the `amount_off` parameter (required if `amount_off` is passed)."
},
{
"disabled": true,
"key": "duration_in_months",
"value": "<integer>",
"description": "Required only if `duration` is `repeating`, in which case it must be a positive integer that specifies the number of months the discount will be in effect."
},
{
"disabled": true,
"key": "expand[0]",
"value": "<string>",
"description": "Specifies which fields in the response should be expanded."
},
{
"disabled": true,
"key": "expand[1]",
"value": "<string>",
"description": "Specifies which fields in the response should be expanded."
},
{
"disabled": true,
"key": "id",
"value": "<string>",
"description": "Unique string of your choice that will be used to identify this coupon when applying it to a customer. If you don't want to specify a particular code, you can leave the ID blank and we'll generate a random code for you."
},
{
"disabled": true,
"key": "max_redemptions",
"value": "<integer>",
"description": "A positive integer specifying the number of times the coupon can be redeemed before it's no longer valid. For example, you might have a 50% off coupon that the first 20 readers of your blog can use."
},
{
"disabled": true,
"key": "name",
"value": "<string>",
"description": "Name of the coupon displayed to customers on, for instance invoices, or receipts. By default the `id` is shown if `name` is not set."
},
{
"disabled": true,
"key": "percent_off",
"value": "<number>",
"description": "A positive float larger than 0, and smaller or equal to 100, that represents the discount the coupon will apply (required if `amount_off` is not passed)."
},
{
"disabled": true,
"key": "redeem_by",
"value": "<unix-time>",
"description": "Unix timestamp specifying the last time at which the coupon can be redeemed. After the redeem_by date, the coupon can no longer be applied to new customers."
}
]
}
},
@dawn-stripe I think I got your requirement. Please add the following option while converting - requestParametersResolution: 'Example'
. You'll have to define your example values in the following way :
properties:
id:
type: integer
example: 1
metadata:
anyOf:
- type: string
example: example metadata key, replace with your key and value
- additionalProperties:
type: string
type: object
description: Set of [key-value pairs](https://stripe.com/docs/api/metadata) that
you can attach to an object. This can be useful for storing additional information
about the object in a structured format. Individual keys can be unset by posting
an empty value to them. All keys can be unset by posting an empty value to `metadata`.
This should work fine.
@dawn-stripe For the given example, there is no concrete definition for metadata
provided. According to OpenAPI spec, deepObject
style is applicable only for object
. Here for first schema resolved object will be empty and second schema which is of type: string
will not create correct serialization. You can add an example like given below to make sure properties are retained after conversion.
"metadata": {
"anyOf": [
{
"additionalProperties": {
"type": "string"
},
"type": "object",
"example": {
"hello": "123",
"world": "!"
}
},
{
"type": "string"
}
],
"description": "Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to `metadata`."
}
I'll close this issue for now, feel free to open it if you have any further questions.
When we convert our spec, we have a polymorphic parameter that seems to be dropped in the conversion. It's defined in the following manner:
W/in the requestBody we have the field encoded as a deepObject:
W/in the schema for the request we have the property defined as 'anyOf' like this:
When I try to trace through why it's getting ignored, it looks like it's being ignored here because the
paramValue
isn't an object but rather a"<object>"
String. I think this maybe generated when the schemaFakerCache is generated but I had trouble following what was happening once schemaFaker was invoked.