thim81 / openapi-format

Format an OpenAPI document by ordering, formatting and filtering fields.
MIT License
77 stars 14 forks source link

sort - order not always preserved on certain sub-objects #81

Open ed-randall-blk opened 10 months ago

ed-randall-blk commented 10 months ago

My goal is to create normalised openapi.json files which developers can confidently review in a PR before deploying to apigee. This tool seems promising in helping us achieve that.

Unfortunately I'm experiencing unexpected sort side-effects which run contrary to the described behaviour:

The fields that are not specified will keep their order like it is in the original OpenAPI document, so only defined fields will be re-ordered.

Just using the default sorting, sub-properties eg auditStatus seem to have a reverse-alpha sort applied. Is there a way to configure that (other than essentially declaring the entire schema ordering in the config file, right down to the leaf level)?

Input:

            "schema": {
              "items": {
                "properties": {
                  "auditStatus": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "columnType": {
                    "type": "string"
                  },
                  "createdBy": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "createdDate": {
                    "format": "date-time",
                    "readOnly": true,
                    "type": "string"
                  },
                  "customValidationType": {
                    "type": "string"
                  },
                  "dataContractColumnValidations": {
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "customValidationId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "dataContractColumnId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "id": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "lastModifiedBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "lastModifiedDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        }
                      },
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "description": {
                    "type": "string"
                  },
                  "id": {
                    "format": "int32",
                    "readOnly": true,
                    "type": "integer"
                  },
                  "isActive": {
                    "type": "boolean"
                  },
                  "lastModifiedBy": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "lastModifiedDate": {
                    "format": "date-time",
                    "readOnly": true,
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "parameterType": {
                    "type": "string"
                  },
                  "rule": {
                    "type": "string"
                  },
                  "scalarModelContractValidations": {
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "customValidationId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "id": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "lastModifiedBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "lastModifiedDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "scalarModelContractId": {
                          "format": "int32",
                          "type": "integer"
                        }
                      },
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              },
              "type": "array"
            }
          },

Output:

            "schema": {
              "type": "array",
              "items": {
                "properties": {
                  "auditStatus": {
                    "type": "string",
                    "readOnly": true
                  },
                  "columnType": {
                    "type": "string"
                  },
                  "createdBy": {
                    "type": "string",
                    "readOnly": true
                  },
                  "createdDate": {
                    "type": "string",
                    "format": "date-time",
                    "readOnly": true
                  },
                  "customValidationType": {
                    "type": "string"
                  },
                  "dataContractColumnValidations": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "customValidationId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "dataContractColumnId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "id": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "lastModifiedBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "lastModifiedDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        }
                      },
                      "type": "object"
                    }
                  },
                  "description": {
                    "type": "string"
                  },
                  "id": {
                    "type": "integer",
                    "format": "int32",
                    "readOnly": true
                  },
                  "isActive": {
                    "type": "boolean"
                  },
                  "lastModifiedBy": {
                    "type": "string",
                    "readOnly": true
                  },
                  "lastModifiedDate": {
                    "type": "string",
                    "format": "date-time",
                    "readOnly": true
                  },
                  "name": {
                    "type": "string"
                  },
                  "parameterType": {
                    "type": "string"
                  },
                  "rule": {
                    "type": "string"
                  },
                  "scalarModelContractValidations": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "customValidationId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "id": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "lastModifiedBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "lastModifiedDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "scalarModelContractId": {
                          "type": "integer",
                          "format": "int32"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "type": "object"
              }
            }
          },
thim81 commented 10 months ago

hi @ed-randall-blk

I'll need to investigate this further, on why this sorting is happening.

thim81 commented 8 months ago

hi @ed-randall-blk

The sorting is applied based on the default: "schema": ["description", "**type**", "**items**", "properties", "**format**", "example", "default"] since the properties are part of the "schema" elements in your OpenApi spec.

2023-09-17 at 16 23 53@2x

This is the expected behavior and would help you spot differences more easily since all the "schema" properties are always sorted in the same order.

The property "read-only" is not part of the defined "schema" field order, so it is put at the end. If there were more "undefined" properties, they all would be put at the end but respecting their original order.