当 API 中未发送必填字段值时,如何在 swagger 中自定义错误消息?

问题描述 投票:0回答:4

下面是我的 api.yml:

openapi: 3.0.0
info:
    title: 'AutoDelievery API'
    description: 'AutoDelievery API Documentation'
    termsOfService: 'https://www.yopmail.com'
    contact:
        name: yopmail
        url: 'http://www.yopmail.com'
        email: [email protected]
    license:
        name: yopmail
        url: 'http://www.yopmail.com/licenses/yopmail-AutoDelievery-Licence.html'
    version: 1.0.0-oas3
servers:
    -
        url: 'http://localhost:5055/'
tags:
    -
        name: AutoDelievery
        description: 'AutoDelievery product related APIs'
        externalDocs:
            description: 'Documentation:'
            url: 'http://localhost:5055/external/doc'
paths:
    /autoDelievery:
        post:
            tags: [autoDelievery]
            summary: 'Creates a new autoDelievery record'
            operationId: insertSubscription
            requestBody: {description: 'autoDelievery request body', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}
            responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
    '/autoDelievery/{autoDelieveryID}':
        get:
            tags: [AutoDelievery]
            summary: 'AutoDelievery as per ID'
            description: 'Fetches the AutoDelievery for the provided Id'
            operationId: getAutoDelieveryById
            parameters: [{in: path, name: autoDelieveryID, required: true, schema: {type: string}}]
            responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
        delete:
            tags: [autoDelievery]
            summary: 'Delete AutoDelievery as per ID'
            description: 'Finds the autoDelievery for the provided Id and deletes the same'
            operationId: deleteAutoDelieveryById
            parameters: [{in: path, name: autoDelieveryID, required: true, schema: {type: string}}]
            responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
    '/autoDelievery/{autoDelieveryID}/payment':
        put:
            tags: [AutoDelievery]
            summary: 'Updates autoDelievery payment details'
            parameters: [{in: path, name: autoDelieveryID, description: 'AutoDelievery Id of which payment details are to be updated', required: true, schema: {type: string}}]
            operationId: updatePayment
            requestBody: {content: {application/json: {schema: {$ref: '#/components/schemas/PaymentMethod'}}}}
            responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
    '/autoDelievery/{autoDelieveryId}/frequency':
        put:
            tags: [AutoDelievery]
            summary: 'Updates AutoDelievery frequency, quantity and end data.'
            parameters: [{in: path, name: autoDelieveryId, description: 'AutoDelievery Id of which frequency is to be updated', required: true, schema: {type: string}}]
            operationId: updateFrequency
            requestBody: {content: {application/json: {schema: {$ref: '#/components/schemas/Frequency'}}}}
            responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
components:
    schemas:
        SubscriptionList:
            type: object
            properties: {count: {type: integer}, result: {type: array, items: {$ref: '#/components/schemas/AutoDelievery'}}, page: {type: integer}}
        DataEntity:
            type: object
            properties: {id: {type: string}, lastModifiedDate: {type: string}, createdDate: {type: string}}
        AutoDelievery:
            allOf: [{$ref: '#/components/schemas/DataEntity'}, {type: object, required: [userId, clientId, quantity, frequency, payment, product, shippingAddress], properties: {userId: {type: string}, clientId: {type: string}, parentSubscriptionId: {type: string}, product: {$ref: '#/components/schemas/Product'}, quantity: {type: integer, minimum: 1}, frequency: {type: number, minimum: 1}, payment: {$ref: '#/components/schemas/PaymentMethod'}, paymentMethodId: {type: string}, shippingMethodId: {type: string}, nextOrderDate: {type: string}, subscriptionStartDate: {type: string}, subscriptionEndDate: {type: string}, shippingMethod: {type: string}, shippingAddress: {$ref: '#/components/schemas/Address'}}}]
        Product:
            type: object
            required: [productId]
            properties: {productId: {type: string}, productDescription: {type: string}}
        PaymentMethod:
            type: object
            required: [billingAddress]
            properties: {createdDate: {type: string}, modifiedDate: {type: string}, paymentType: {type: string}, billingAddress: {$ref: '#/components/schemas/Address'}}
            discriminator: {propertyName: paymentType}
        Frequency:
            type: object
            required: [frequency, quantity]
            properties: {frequency: {type: number, minimum: 1}, subscriptionEndDate: {type: string}, quantity: {type: integer, minimum: 1}}
        Card:
            allOf: [{$ref: '#/components/schemas/PaymentMethod'}, {type: object, required: [nameOnCard, lastFourDigits, expiryMonth, expiryYear], properties: {nameOnCard: {type: string}, lastFourDigits: {type: string}, token: {type: string}, expiryMonth: {type: string, minLength: 2, maxLength: 2}, expiryYear: {type: string, format: year}}, discriminator: {propertyName: paymentType}}]
        PayPal:
            allOf: [{$ref: '#/components/schemas/PaymentMethod'}, {type: object, required: [accountId], properties: {accountId: {type: string}}}]
        Payment:
            type: object
            properties: {payment: {allOf: [{$ref: '#/components/schemas/PaymentMethod'}], discriminator: {propertyName: paymentType}}}
        Address:
            type: object
            required: [firstName, lastName, addressLine1, city, state, postalCode, country]
            properties: {prefix: {type: string}, firstName: {type: string}, middleName: {type: string}, lastName: {type: string}, suffix: {type: string}, title: {type: string}, companyName: {type: string}, addressLine1: {type: string}, addressLine2: {type: string}, city: {type: string}, state: {type: string}, postalCode: {type: string}, country: {type: string}, phoneNumber: {type: string}, mobilePhoneNumber: {type: string}}
        Status:
            type: object
            required: [status]
            properties: {status: {type: string}, details: {type: string}}
        Shipping:
            type: object
            properties: {shippingMethodId: {type: string}, shippingMethod: {type: string}}
        PaymentAuthorization:
            type: object
            properties: {authId: {type: string}}
        CommerceItem:
            type: object
            required: [subscriptionId, quantity, product]
            properties: {subscriptionId: {type: string}, product: {$ref: '#/components/schemas/Product'}, quantity: {type: number, minimum: 1}, itemUnitPrice: {type: number}, itemTotalPrice: {type: number}, itemDiscount: {type: number}}
        ErrorResponse:
            type: object
            required: [errorMessage]
            properties: {field: {type: string}, errorMessage: {type: string}}
        ErrorResponseList:
            type: object
            required: [errors]
            properties: {errors: {type: array, items: {$ref: '#/components/schemas/ErrorResponse'}}}
        NoSubscriptionResponse:
            allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]
        AutoDelieveryError:
            allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]
        NoOrderResponse:
            allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]

我的示例 API 是:

  "id": "string",
  "lastModifiedDate": "string",
  "createdDate": "string",
  "userId": null,
  "clientId": "string",
  "parentSubscriptionId": "string",
  "product": {
    "productId": "string",
    "productDescription": "string"
  },
  "quantity": 0,
  "frequency": 0,
  "payment": {
    "createdDate": "string",
    "modifiedDate": "string",
    "paymentType": "string",
    "billingAddress": {
      "prefix": "string",
      "firstName": "string",
      "middleName": "string",
      "lastName": "string",
      "suffix": "string",
      "title": "string",
      "companyName": "string",
      "addressLine1": "string",
      "addressLine2": "string",
      "city": "string",
      "state": "string",
      "postalCode": "string",
      "country": "string",
      "phoneNumber": "string",
      "mobilePhoneNumber": "string"
    }
  },
  "paymentMethodId": "string",
  "shippingMethodId": "string",
  "nextOrderDate": "string",
  "subscriptionStartDate": "string",
  "subscriptionEndDate": "string",
  `enter code here`"shippingMethod": "string",
  "shippingAddress": {
    "prefix": "string",
    "firstName": "string",
    "middleName": "string",
    "lastName": "string",
    "suffix": "string",
    "title": "string",
    "companyName": "string",
    "addressLine1": "string",
    "addressLine2": "string",
    "city": "string",
    "state": "string",
    "postalCode": "string",
    "country": "string",
    "phoneNumber": "string",
    "mobilePhoneNumber": "string"
  }
}

我收到以下格式的错误响应:

{
    "errors": [
        {
            "field": "userId",
            "errorMessage": "must not be null"
        }
    ]
}

我应该怎样做才能获得自定义的错误消息?

spring-boot swagger swagger-editor
4个回答
2
投票

Swagger 在创建 POJO 时将

@NotNull
注释放在
required
字段上。

消息插值可以通过在类路径中创建

ValidationMessages.properties
文件来完成,如下所示:

javax.validation.constraints.NotNull.message=CUSTOMIZED ERROR MESSAGE

它将覆盖来自的默认错误消息

/org/hibernate/validator/ValidationMessages.properties

2
投票

这可以通过添加 ControllerAdvice 类轻松解决。找出从堆栈跟踪中抛出的异常并为其编写一个处理程序。在处理程序中,当发生此类异常时,您将能够抛出自定义错误消息。

这里是 ExceptionHandler

的一些参考

0
投票

可以实现spring的抽象类OncePerRequestFilter并重写 doFilterInternal方法。 在此方法中,使用 httpservletRerquest 添加验证,并使用 ResponseStatusException 返回自定义消息。 参考- https://www.baeldung.com/spring-onceperrequestfilter


0
投票

据我研究,OpenApi 没有内置机制来覆盖验证消息。但是,您可以使用

x-field-extra-annotation
扩展向属性字段添加自定义或其他注释来实现此目的。

components:

  schemas:
    #...

    Address:
      type: object
      required: [firstName, lastName]
      properties:
        email:
          type: string
          x-field-extra-annotation: "@javax.validation.constraints.NotNull(message = \"your custom message\")"
        firstName:
          type: string
        lastName:
          type: string

要添加更多验证器注释,只需将它们放在同一行即可,

x-field-extra-annotation: "@javax.validation.constraints.NotNull(message = \"your customer message\") @javax.validation.constraints.Size(min = 2, max = 50, message = \"Lastname must be between 2 and 50 characters\")"

注意:对于 spring boot 3.xjakarta-validation,请使用

jakarta
而不是
javax

© www.soinside.com 2019 - 2024. All rights reserved.