2017-10-12 185 views
0

我的問題涉及到posted here如何將響應實體包含在Swagger中的主模板響應中?

我不得不改寫我的問題,因爲我覺得前面的一個太冗長了。再來一次吧!

我有一個REST API返回的資產清單,它的編碼是這樣的:

@GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getAllAssets() { 
     List<Asset> assets = new ArrayList<Asset>(); 
     for(int i=1; i<11; i++) { 
      assets.add(new Asset(i)); 
     } 

     return RestResponse.create(Status.OK, "10 assets Fetched successfully!", assets); 
    } 

它產生的反應是這樣的:

{ 
    "message":"10 assets Fetched successfully!", 
    "content": [{ 
     "id":"1", 
     "type":"LPTP", 
     "owner":"Ram", 
     "serialNo":"WDKLL3234K3", 
     "purchasedOn":"01 Jan 2017" 

    }, 
    { 
     "id":"2", 
     "type":"LPTP", 
     "owner":"Ram", 
     "serialNo":"WDKLL3234K3", 
     "purchasedOn":"01 Jan 2017" 

    }, 
    ... 
    ] 
} 

我有超過60個服務在我的應用程序中遵循相同的響應模板:

{ 
     "message":"Message the service wants to send to the client", 
     "content": { 
      .... 
      Entity returned by the service 
      .... 
     } 
} 

以下是其餘表示我們的響應模板響應POJO:

public class RestResponse { 
     private String message; 
     private Object content; 

     public String getMessage() { 
      return message; 
     } 
     public void setMessage(String message) { 
      this.message = message; 
     } 
     public Object getContent() { 
      return content; 
     } 
     public void setContent(Object content) { 
      this.content = content; 
     } 

     private RestResponse(String message, Object content) { 
      this.message = message; 
      this.content = content; 
     } 

     public static Response create(Response.Status status, String message, Object content) { 
      return Response.status(status).entity(new RestResponse(message, content)).build(); 
     } 
} 

現在我們使用記錄揚鞭所有API,並遇到了一個問題。

由於我們返回RestResponse類爲我們所有的API,我寫了下面的註釋爲我的操作:

@ApiOperation(value="Fetches all available assets", response=RestResponse.class, responseContainer="List") 

做,是爲RestResponse類定義的架構是什麼揚鞭看起來是這樣的:

"definitions": { 
    "RestResponse": { 
     "type": "object", 
     "properties": { 
     "message": { 
      "type": "string" 
     }, 
     "content": { 
      "type": "object" 
     } 
     } 
    } 
} 

在這裏,我沒有得到有關content屬性內的對象屬性的任何信息或模式。

我明白這是因爲Swagger不能使用通用對象。

所以,如果我改變我的@ApiOperation註釋下面的一個:

@ApiOperation(value="Fetches all available assets", response=Asset.class, responseContainer="List") 

在上述情況下,揚鞭描述Asset實體的屬性,但很明顯,message屬性(我的迴應模板)不見了。

我的問題是我想擁有兩者。我的響應模板的content屬性可以是任何實體。

那麼,我可以設置response=Asset.class並指示Swagger將Asset附加到RestResponsecontent屬性之前,它將其文檔?或者我可以通過其他方式實現這一目標?

希望我這次精確!

謝謝, Sriram Sridharan。

編輯 - 我嘗試了馬克·努裏的建議 後,我創建了一個類似RestServiceResponse.class與通用對象,並設置responseReference屬性爲我@ApiOperationRestServiceResponse<Asset>。下面是我得到的JSON。

{ 
    "swagger": "2.0", 
    "info": { 
    "version": "1.0.0", 
    "title": "" 
    }, 
    "host": "localhost:7070", 
    "basePath": "/assets/rest", 
    "tags": [ 
    { 
     "name": "Assets" 
    } 
    ], 
    "schemes": [ 
    "http" 
    ], 
    "paths": { 
    "/assets/{id}": { 
     "get": { 
     "tags": [ 
      "Assets" 
     ], 
     "summary": "Fetches information about a single asset", 
     "description": "", 
     "operationId": "fetchAssetDetail", 
     "produces": [ 
      "application/json" 
     ], 
     "parameters": [ 
      { 
      "name": "id", 
      "in": "path", 
      "required": true, 
      "type": "integer", 
      "format": "int32" 
      } 
     ], 
     "responses": { 
      "200": { 
      "description": "successful operation", 
      "schema": { 
       "$ref": "#/definitions/RestServiceResponse<Asset>" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

如您所見,Definitions部分完全缺失。我錯過了什麼嗎?

我有我的project in GitHub,以防您需要查看整個代碼。請幫幫我。

回答

0

再次感謝Marc Nuri!

我可能找到了適用於我的場景的解決方案。這就是我所做的。我有我的RestServiceResponse類一樣在我的問題(最近編輯)提到的,我只是通過AssetService類修改通過添加static final class這樣的:

private static final class AssetResponse extends RestServiceResponse<Asset> { 
     private Asset data; 
} 

一旦做到這一點,我改變我@ApiOperation註釋本:

@ApiOperation(value="Fetches an asset by ID", produces="application/json", response=AssetResponse.class) 

現在,這基本上做的是,爲純文檔的目的,似乎只是更換泛型類型的RestServiceResponse類在編譯時特定Asset型,使揚鞭可以定義對象。

現在,當我運行Swagger JSON URL時,我得到了一個完美的文檔!

{ 
    "swagger": "2.0", 
    "info": { 
    "version": "1.0.0", 
    "title": "" 
    }, 
    "host": "localhost:7070", 
    "basePath": "/assets/rest", 
    "tags": [ 
    { 
     "name": "Assets" 
    } 
    ], 
    "schemes": [ 
    "http" 
    ], 
    "paths": { 
    "/assets/{id}": { 
     "get": { 
     "tags": [ 
      "Assets" 
     ], 
     "summary": "Fetches information about a single asset", 
     "description": "", 
     "operationId": "fetchAssetDetail", 
     "produces": [ 
      "application/json" 
     ], 
     "parameters": [ 
      { 
      "name": "id", 
      "in": "path", 
      "required": true, 
      "type": "integer", 
      "format": "int32" 
      } 
     ], 
     "responses": { 
      "200": { 
      "description": "successful operation", 
      "schema": { 
       "$ref": "#/definitions/AssetResponse" 
      } 
      } 
     } 
     } 
    } 
    }, 
    "definitions": { 
    "Asset": { 
     "type": "object", 
     "required": [ 
     "name", 
     "owner", 
     "purchaseDate", 
     "type" 
     ], 
     "properties": { 
     "id": { 
      "type": "integer", 
      "format": "int32", 
      "description": "The internal unique ID of the Asset" 
     }, 
     "name": { 
      "type": "string", 
      "description": "Name of the asset" 
     }, 
     "type": { 
      "type": "string", 
      "description": "Name of the asset", 
      "enum": [ 
      "Laptop", 
      "Desktop", 
      "Internet Dongle", 
      "Tablet", 
      "Smartphone" 
      ] 
     }, 
     "owner": { 
      "type": "string", 
      "description": "ID of the person who owns this asset" 
     }, 
     "purchaseDate": { 
      "type": "string", 
      "format": "date", 
      "description": "Date when this asset was purchased" 
     } 
     } 
    }, 
    "AssetResponse": { 
     "type": "object", 
     "properties": { 
     "message": { 
      "type": "string" 
     }, 
     "content": { 
      "$ref": "#/definitions/Asset" 
     } 
     } 
    } 
    } 
} 

我還不知道這是否是最有效的解決方案,但現在對我來說足夠好了。請分享你的想法。

0

我們在我們的微服務響應中使用了類似的結構。

唯一的區別是我們的響應容器(即RestResponse)沒有原始類型,併爲消息正文/內容使用Type參數。

請嘗試將RestResponse更改爲:

public class RestResponse<T> { 
    private String message; 
    private T content; 

    public String getMessage() { 
     return message; 
    } 
    public void setMessage(String message) { 
     this.message = message; 
    } 
    public T getContent() { 
     return content; 
    } 
    public void setContent(T content) { 
     this.content = content; 
    } 

    private RestResponse(String message, T content) { 
     this.message = message; 
     this.content = content; 
    } 

    public static <T> Response create(Response.Status status, String message, Object content) { 
     return Response.status(status).entity(new RestResponse(message, content)).build(); 
    } 
} 

然後標註您的終端是這樣的:

@ApiOperation(
      value="Fetches all available assets", 
      responseReference = "RestResponse<List<Asset>>") 

這是爲了招搖的最新版本確定。

+0

嗨@MarcNuri,我嘗試了你的建議,但仍然面臨着或多或少的同樣的問題。你能幫我解決嗎?我已經用細節編輯了這個問題。 – sriramsridharan

+0

嗨。在我們的項目中,我們使用Swagger-ui來使用Spring和Swagger2。也許它有不同的行爲。我在解決方案中描述的內容沒有記錄在Swagger的庫文檔中,但正在運行。 我會嘗試檢查您的代碼,看看我能否找到正在發生的事情。 –