admin管理员组

文章数量:1353240

This is what response body I am trying to represent

[
  {
    measured_at | time_bucket,
    [value] | [latitude, longitude, altitude] | [running, walking]
  }...
]

Above is a bit of a shorthand notation for an array of JSON objects that will all have: the measured_at OR time_bucket, and either value OR latitide,longitude,altitude OR runnning,walking

The closest schema I have written to achieving this is:

measurementsGetDynamicResponse:
      type: array
      items:
        type: object
        allOf:
          # Combine measured_at or time_bucket with one of the measurement data combinations
          - oneOf:
              - properties:
                  measured_at:
                    type: string
                    format: date-time
                    description: "Timestamp of the data point"
              - properties:
                  time_bucket:
                    type: string
                    description: "The time bucket for calculating the aggregation"
          - properties:
              value:
                type: integer
          - properties:
              latitude:
                type: number
                format: float
                description: "Latitude in decimal degrees"
              longitude:
                type: number
                format: float
                description: "Longitude in decimal degrees"
              altitude:
                type: number
                format: float
                description: "Altitude in meters"
          - properties:
              running:
                type: integer
                description: "Number of running steps"
              walking:
                type: integer
                description: "Number of walking steps"

However, this schema doesn't separate the measurement groups, instead combining them all into one group:

(Swagger Example)

[
  {
    "measured_at": "2025-04-01T19:53:13.291Z",
    "value": 0,
    "latitude": 0,
    "longitude": 0,
    "altitude": 0,
    "running": 0,
    "walking": 0
  },
  {
    "time_bucket": "string",
    "value": 0,
    "latitude": 0,
    "longitude": 0,
    "altitude": 0,
    "running": 0,
    "walking": 0
  }
]

I tried grouping the measurement groups in a - oneOf field:

    measurementsGetDynamicResponse:
      type: array
      items:
        type: object
        allOf:
          # Combine measured_at or time_bucket with one of the measurement data combinations
          - oneOf:
              - properties:
                  measured_at:
                    type: string
                    format: date-time
                    description: "Timestamp of the data point"
              - properties:
                  time_bucket:
                    type: string
                    description: "The time bucket for calculating the aggregation"
          - oneOf:
              - properties:
                  value:
                    type: integer
              - properties:
                  latitude:
                    type: number
                    format: float
                    description: "Latitude in decimal degrees"
                  longitude:
                    type: number
                    format: float
                    description: "Longitude in decimal degrees"
                  altitude:
                    type: number
                    format: float
                    description: "Altitude in meters"
              - properties:
                  running:
                    type: integer
                    description: "Number of running steps"
                  walking:
                    type: integer
                    description: "Number of walking steps"

But it kept the measurement group together but separated them from the timestamps

(Swagger Example)

[
  {
    "measured_at": "2025-04-01T19:57:32.452Z"
  },
  {
    "time_bucket": "string"
  },
  {
    "value": 0
  },
  {
    "latitude": 0,
    "longitude": 0,
    "altitude": 0
  },
  {
    "running": 0,
    "walking": 0
  }
]

Any advice on how I can get the schema I am looking for?

This is what response body I am trying to represent

[
  {
    measured_at | time_bucket,
    [value] | [latitude, longitude, altitude] | [running, walking]
  }...
]

Above is a bit of a shorthand notation for an array of JSON objects that will all have: the measured_at OR time_bucket, and either value OR latitide,longitude,altitude OR runnning,walking

The closest schema I have written to achieving this is:

measurementsGetDynamicResponse:
      type: array
      items:
        type: object
        allOf:
          # Combine measured_at or time_bucket with one of the measurement data combinations
          - oneOf:
              - properties:
                  measured_at:
                    type: string
                    format: date-time
                    description: "Timestamp of the data point"
              - properties:
                  time_bucket:
                    type: string
                    description: "The time bucket for calculating the aggregation"
          - properties:
              value:
                type: integer
          - properties:
              latitude:
                type: number
                format: float
                description: "Latitude in decimal degrees"
              longitude:
                type: number
                format: float
                description: "Longitude in decimal degrees"
              altitude:
                type: number
                format: float
                description: "Altitude in meters"
          - properties:
              running:
                type: integer
                description: "Number of running steps"
              walking:
                type: integer
                description: "Number of walking steps"

However, this schema doesn't separate the measurement groups, instead combining them all into one group:

(Swagger Example)

[
  {
    "measured_at": "2025-04-01T19:53:13.291Z",
    "value": 0,
    "latitude": 0,
    "longitude": 0,
    "altitude": 0,
    "running": 0,
    "walking": 0
  },
  {
    "time_bucket": "string",
    "value": 0,
    "latitude": 0,
    "longitude": 0,
    "altitude": 0,
    "running": 0,
    "walking": 0
  }
]

I tried grouping the measurement groups in a - oneOf field:

    measurementsGetDynamicResponse:
      type: array
      items:
        type: object
        allOf:
          # Combine measured_at or time_bucket with one of the measurement data combinations
          - oneOf:
              - properties:
                  measured_at:
                    type: string
                    format: date-time
                    description: "Timestamp of the data point"
              - properties:
                  time_bucket:
                    type: string
                    description: "The time bucket for calculating the aggregation"
          - oneOf:
              - properties:
                  value:
                    type: integer
              - properties:
                  latitude:
                    type: number
                    format: float
                    description: "Latitude in decimal degrees"
                  longitude:
                    type: number
                    format: float
                    description: "Longitude in decimal degrees"
                  altitude:
                    type: number
                    format: float
                    description: "Altitude in meters"
              - properties:
                  running:
                    type: integer
                    description: "Number of running steps"
                  walking:
                    type: integer
                    description: "Number of walking steps"

But it kept the measurement group together but separated them from the timestamps

(Swagger Example)

[
  {
    "measured_at": "2025-04-01T19:57:32.452Z"
  },
  {
    "time_bucket": "string"
  },
  {
    "value": 0
  },
  {
    "latitude": 0,
    "longitude": 0,
    "altitude": 0
  },
  {
    "running": 0,
    "walking": 0
  }
]

Any advice on how I can get the schema I am looking for?

Share Improve this question edited Apr 2 at 15:42 Jeremy Fiel 3,3402 gold badges12 silver badges26 bronze badges asked Apr 1 at 20:02 BEANB00ZLEDBEANB00ZLED 33 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Assume you are using OAS 3.0.x, where JSON Schema Draft-04 is necessary

This ends up being a very verbose schema because you need to constrain additional properties from each oneOf subschema, but also use allOf to create all of the possible values you are seeking.

each of time_bucket and measured_at must be defined for each oneOf option, then we use oneOf>required to only allow one of those values. Then each set of properties associated to the measurement types are defined with an empty schema because this allows you to use additionalProperties: false as a sibling to allOf.

$schema: http://json-schema./draft-04/schema#
type: object
properties:
  measurementsGetDynamicResponse:
    type: array
    items:
      oneOf:
        - $ref: '#/definitions/measurement_and_value'
        - $ref: '#/definitions/measurement_and_workouts'
        - $ref: '#/definitions/measurement_and_geography'
definitions:
  geographyType:
    type: object
    properties:
      latitude:
        type: number
        format: float
        description: Latitude in decimal degrees
      longitude:
        type: number
        format: float
        description: Longitude in decimal degrees
      altitude:
        type: number
        format: float
        description: Altitude in meters
  workoutType:
    type: object
    properties:
      running:
        type: integer
        description: Number of running steps
      walking:
        type: integer
        description: Number of walking steps
  valueType:
    type: object
    properties:
      value:
        type: integer
  measurementType:
    type: object
    properties:
      measured_at:
        type: string
        format: date-time
        description: Timestamp of the data point
      time_bucket:
        type: string
        description: The time bucket for calculating the aggregation
  measurement_and_value:
    additionalProperties: false
    properties:
      time_bucket: {}
      measured_at: {}
      value: {}
    oneOf:
      - required:
          - measured_at
      - required:
          - time_bucket
    allOf:
      - $ref: "#/definitions/measurementType"
      - $ref: "#/definitions/valueType"
  measurement_and_workouts:
    additionalProperties: false
    properties:
      time_bucket: {}
      measured_at: {}
      running: {}
      walking: {}
    oneOf:
      - required:
          - measured_at
      - required:
          - time_bucket
    allOf:
      - $ref: "#/definitions/measurementType"
      - $ref: "#/definitions/workoutType"
  measurement_and_geography:
    additionalProperties: false
    properties:
      time_bucket: {}
      measured_at: {}
      longitude: {}
      latitude: {}
      altitude: {}
    oneOf:
      - required:
          - measured_at
      - required:
          - time_bucket
    allOf:
      - $ref: "#/definitions/measurementType"
      - $ref: "#/definitions/geographyType"

valid examples


{
    "measurementsGetDynamicResponse": [
        {
            "time_bucket": "a time",
            "running": 1,
            "walking": 3
        },
        {
            "measured_at": "2023-01-23",
            "value": 1
        },
        {
            "time_bucket": "test",
            "longitude": 1.00
        }
    ]
}

本文标签: yamlMultiple oneOf Groups With OpenAPI 30 definition not validating correctlyStack Overflow