biocad / openapi3

OpenAPI 3.0 data model
BSD 3-Clause "New" or "Revised" License
39 stars 53 forks source link

Add `nullable` attribute #71

Open wwwater opened 1 year ago

wwwater commented 1 year ago

Hi, in OpenAPI standard a field needs to be marked as nullable: true if it can contain null value. When not using omitNothingFields in Aeson (default setting), openapi3 lib doesn't mark these fields as nullable, but it should.

The function fromAesonOptions ignores omitNothingFields, probably it would be better to not ignore it but use to determine whether to add the nullable attribute or not.

What do you think?

avandecreme commented 1 year ago

I am facing this issue as well. Relying on omitNothingFields is probably not enough because you may want to not have the same behavior for all Maybe fields of a given record. For example you may want to encode this:

data Foo = Foo
  { optionalNotNullable :: Maybe String
  , optionalNullable :: Maybe String
  , requiredNullable :: Maybe String
  , requiredNotNullable :: String
  }

Which should have a schema looking like this:

{
  "properties": {
    "optionalNotNullable": { "type": "string" },
    "optionalNullable": { "type": "string", "nullable": true },
    "requiredNullable": { "type": "string", "nullable": true },
    "requiredNotNullable":  { "type": "string" }
  },
  "required": ["requiredNullable", "requiredNotNullable"],
  "type": "object"
}

I can't think of a good suggestion on how to proceed though.

bgohla commented 1 year ago

One solution might be to use newtype wrappers for the field types, and typeclass instances, that implement each of the possible behaviors.

stevladimir commented 1 year ago

Just to note: IIRC nullable keyword was dropped in the latest (3.1) OpenAPI specification, so it may be of little sense to add support for it now.

pbrisbin commented 7 months ago

Came here because I'm also currently being bitten by this. I think it's still worth tracking this feature even though 3.1 is dropping nullable because in 3.1 you would represent what used to be:

foo:
  type: string
  nullable: true

By instead doing:

foo:
  type:
    anyOf:
      - type: string
      - type: "null"

So there is still a feature here about changing the spec based on omitNothingFields; it's just that for 3.0 it's "add nullable" and for 3.1 it's "switch to anyOf with a type: null element".