Skip to content

protoc-gen-openapiv2: oneof fields incorrectly marked as required with use_proto3_field_semantics=true #6334

@sessa

Description

@sessa

Bug Report

When using use_proto3_field_semantics=true, oneof member fields are incorrectly added to the required array of the parent message's OpenAPI schema. This is semantically wrong because a oneof means at most one of the fields can be set — they should never all be required simultaneously.

Steps to Reproduce

Given a proto message with a oneof:

message Filter {
  oneof filter_group_or_value {
    FilterList list = 1;
    FilterRule rule = 2;
  }
}

Run protoc-gen-openapiv2 with use_proto3_field_semantics=true.

Expected Output

oneof fields should be excluded from the required array, since only one can be set at a time:

"Filter": {
  "type": "object",
  "properties": {
    "list": {
      "$ref": "#/definitions/FilterList"
    },
    "rule": {
      "$ref": "#/definitions/FilterRule"
    }
  }
}

Actual Output

Both oneof members are marked as required:

"Filter": {
  "type": "object",
  "properties": {
    "list": {
      "$ref": "#/definitions/FilterList"
    },
    "rule": {
      "$ref": "#/definitions/FilterRule"
    }
  },
  "required": [
    "list",
    "rule"
  ]
}

Analysis

The use_proto3_field_semantics=true option marks all proto3 fields that are not optional as required. However, it does not check whether a field is part of a oneof group. Fields within a oneof should be treated as implicitly optional (only one can be present), so they should be excluded from the required list.

A potential fix would be to check field.OneofIndex in updateSwaggerObjectFromFieldBehavior and skip adding oneof members to the required array when use_proto3_field_semantics is enabled.

Environment

  • Plugin: buf.build/grpc-ecosystem/openapiv2:v2.27.3
  • Configuration:
    opt:
      - use_proto3_field_semantics=true
      - json_names_for_fields=true
      - output_format=json
    

Workaround

Currently the only workarounds are:

  1. Remove use_proto3_field_semantics=true (makes all fields optional)
  2. Post-process the generated swagger to strip oneof fields from required arrays
  3. Use per-field google.api.field_behavior = REQUIRED annotations instead of the blanket flag

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions