Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a property with a mixed data type in Swagger

I already have a working swagger document that generates documentation using the Swagger-UI project, but I'm running into a minor issue.

Mongoose supports a data type of Mixed, which is basically an unstructured object that can contain anything. However, according to the Swagger specification the only possible values for a property's type are string, integer, number, boolean and array. I've been unable to find anything in the documentation, on Google, or in the open issues for the Swagger-Spec project on GitHub that would allow for mixed data types.

In the Swagger-Spec documentation, where they define the type options, they refer to the JSON-Schema project. According to the JSON-Schema specification object should be an option, but it's not listed as a potential value in the Swagger-Spec.

Does anyone know of a way to indicate in a Swagger document that a model's property can contain any value (either a single primitive value or an object)?

Examples

Mongoose schema definition:

var sampleSchema = new mongoose.Schema({
    lookupCodes : { type: [mongoose.Schema.Types.Mixed] },
    address: { type: mongoose.Schema.Types.Mixed }
});

mongoose.model('Sample', sampleSchema);

Usage of the mongoose model:

var Sample = mongoose.model('Sample');
var doc = new Sample();

These are all valid values for the two defined properties:

doc.lookupCodes = ['A', 'B', 3, 4, 5, 'F'];

doc.lookupCodes = ['A', { code: '123' }, 5];

doc.address = '123 Main St., San Jose, CA, 95125';

doc.address = { street: '123 Main St.', city: 'San Jose', state: 'CA', postalCode: '95125'}

Swagger 1.2 document (snippet):

"models": {
    "Sample": {
        "properties": {
            "lookupCodes": {
                "type": "array",
                "items": {
                    "type": "??????"
                },
                "description": "An array of lookup codes. Codes can be strings, numbers or an object containing the `code` property."
            },
            "address": {
                "type": "??????",
                "description": "An address. This value can be a single string, containing all the elements of the address together, or it can be a structured object with each of the elements as separate properties of the object."
            },

I'm simply looking for a way to let the developer viewing the documentation know that a specific property within a model could accept/return any value (primitive variable or an object).

like image 663
Brian Shamblen Avatar asked Jan 06 '15 01:01

Brian Shamblen


People also ask

How can I create a mixed-type array with parameters in Swagger?

OpenAPI 2.0 (Swagger 2.0) does not really support mixed-type array and parameters. The most you can do is to use a typeless schema {} for items, which means the items can be anything (except null) – numbers, objects, strings, etc. You cannot specify the exact types for items, but you can add an example of an array with different item types.

Where are data types used in Swagger?

In the Swagger specification, the data types are used in several locations - Operations, Operation Parameters, Models, and within the data types themselves (arrays). The fields used to describe a given data type are added flatly to the relevant object.

How many files are in a swagger resource?

There is one file per resource. In the Swagger specification, the data types are used in several locations - Operations, Operation Parameters, Models, and within the data types themselves (arrays). The fields used to describe a given data type are added flatly to the relevant object.

How do Swagger properties affect documentation and generated code?

They have no effect on documentation and generated code produced from your Swagger specification. Some comments suggest that the default behavior in Swagger should be to disallow additional properties, but this is not in the Swagger 2.0 spec.


1 Answers

In your question you describe two distinct use cases.

The first is the usage of an array with mixed values, and the second is a specific field that can have any value (be it an object, primitive and potentially an array).

Swagger explicitly doesn't support such modeling. There are several reasons for it, but they concentrate on determinism and language support. While dynamic languages can more easily support non-deterministic APIs, and weakly typed languages can easily support dynamic types, the other languages would suffer for it. APIs are meant for interoperability, being language-independent, so you have to consider these restrictions.

While Swagger is meant as a documentation tool, its ecosystem of tools includes solutions that would need to be able to produce and consume such APIs in virtually any language. Obviously, it cannot have 100% coverage, but it attempts to avoid known issues.

Swagger 2.0 adds much more flexibility in terms of defining models, allowing even free-form objects (and do note - objects, not primitives). While it would be highly not recommended to use in general, there are use cases where it just cannot be avoided, but even strongly-typed languages can deal with it (I can elaborate on the use cases, but it's not relevant to the question at hand).

As added information - think of it from a documentation point of view, and I'll use your address field as an example. What you're saying here, API Wise, is that the address field is a wildcard. You can accept anything to it, and it doesn't have to be an address, doesn't have to have a structure, doesn't have to have specific information. If someone wants, they can use that field to store a nuclear launch code. Now, if this is your intention, then just mark the field as a string value, and if someone wants to send a serialized JSON object as a string, it would fit just as well.

like image 85
Ron Avatar answered Oct 22 '22 18:10

Ron