I have an API endpoint that responds to POST requests with a query parameter of the form:
json_string = '{"items":%20[{"name":%20"chicken",%20"quantity":%201,%20"basePrice":%20499,%20"priceWithModifiers":%20499},%20{"name":%20"soda",%20"quantity":%201,%20"basePrice":%20399,%20"priceWithModifiers":%20399}],%20"salesTax":%20{"id":%20"T8JKFEVBE6F30",%20"name":%20"Sales%20Tax",%20"rate":%20900000,%20"isDefault":%20true},%20"orderType":%20{"id":%20"ZJQ5ND5FZAAVP",%20"taxable":%20true,%20"isDefault":%20true,%20"filterCategories":%20false,%20"isHidden":%20false,%20"hoursAvailable":%20"BUSINESS",%20"isDeleted":%20false}}'
So, the complete url is "endpoint/?{json_string}". I have tried to use content -> application/json -> schema to describe the parameter as a string, but since I must give the parameter a name, there will always be an unwanted "=" somewhere in the query parameter. I do not want to rewrite the api itself.
You can create a similar string in Javascript with
const my_dict = {"items": [5,6,7], "SalesTax": {"id": "foobar"}, "orderType": {"id": "Takeout"}}
query_param = JSON.stringify(my_dict)
or in Python
import json
my_dict = {"items": [5,6,7], "SalesTax": {"id": "foobar"}, "orderType": {"id": "Takeout"}}
query_param = json.dumps(my_dict)
Is there a reason you wouldn't use a POST with a request body? What's the purpose of maintaining the json string in the query? The url is character limited to 2048. If your json string grows past this number, you'll have much bigger problems. The other advantage is you don't need to encode a request body.
POST /endpoint HTTP/1.1
content-type: application/json
{
"items": [
{
"name": "chicken",
"quantity": 1,
"basePrice": 499,
"priceWithModifiers": 499
},
{
"name": "soda",
"quantity": 1,
"basePrice": 399,
"priceWithModifiers": 399
}
],
"salesTax": {
"id": "T8JKFEVBE6F30",
"name": "Sales Tax",
"rate": 900000,
"isDefault": true
},
"orderType": {
"id": "ZJQ5ND5FZAAVP",
"taxable": true,
"isDefault": true,
"filterCategories": false,
"isHidden": false,
"hoursAvailable": "BUSINESS",
"isDeleted": false
}
}
This is defined as a JSON Schema as follows:
{
"$id": "itemWithPricing",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"items": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"quantity": {
"type": "number"
},
"basePrice": {
"type": "number"
},
"priceWithModifiers": {
"type": "number"
}
}
}
},
"salesTax": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"rate": {
"type": "number"
},
"isDefault": {
"type": "boolean"
}
}
},
"orderType": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"taxable": {
"type": "boolean"
},
"isDefault": {
"type": "boolean"
},
"filterCategories": {
"type": "boolean"
},
"isHidden": {
"type": "boolean"
},
"hoursAvailable": {
"type": "string"
},
"isDeleted": {
"type": "boolean"
}
}
}
}
}
Then you can use it in your OpenAPI description
{
"openapi": "3.1.0",
"info": {},
"servers": [],
"paths": {
"/endpoint": {
"post": {
"summary": "create a new item with pricing",
"parameters": [],
"requestBody": {
"$ref": "#/components/requestBodies/itemsWithPricing"
},
"responses": {
"201": {
"description": "Created",
"headers": {
"location": {
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
}
},
"components": {
"schemas": {
"itemsWithPricing": {
"$id": "itemWithPricing",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"items": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"quantity": {
"type": "number"
},
"basePrice": {
"type": "number"
},
"priceWithModifiers": {
"type": "number"
}
}
}
},
"salesTax": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"rate": {
"type": "number"
},
"isDefault": {
"type": "boolean"
}
}
},
"orderType": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"taxable": {
"type": "boolean"
},
"isDefault": {
"type": "boolean"
},
"filterCategories": {
"type": "boolean"
},
"isHidden": {
"type": "boolean"
},
"hoursAvailable": {
"type": "string"
},
"isDeleted": {
"type": "boolean"
}
}
}
}
}
},
"requestBodies": {
"itemsWithPricing": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/itemsWithPricing"
}
}
},
"required": true
}
}
}
}