API Interface Development: Interface Development Returns Result Solution

Posted by sriusa on Mon, 09 Dec 2019 01:44:42 +0100

abstract

If the front-end and back-end are separated for project development, the better way for front-end and back-end interaction is to use HTTP+JSON.How can an interface return results that are more concise, elegant, and reasonable, and that can be made clear to front-end developers without increasing the workload for back-end developers?

Start of Text

Hello, everyone, long time no see.I have been planning for the personal website to be revamped in the 2020 version, so this article is also the last one in 2019. Of course, I have to put some thought into trying to say what I want to say one by one, explain it clearly and thoroughly.

If the front-end and back-end are separated for project development, the better way for front-end and back-end interaction is to use HTTP+JSON.How can an interface return results that are more concise, elegant, and reasonable, and that can be made clear to front-end developers without increasing the workload for back-end developers?

To do this, I have written a set of solutions for API interface development returning results. api-result , has been opened source and uploaded to Central warehouse You are welcome to criticize and make corrections.

API Explanation

Entity Class

Entity classes that satisfy the use of each scenario are provided as follows:

ResultModel

This class is the base entity class with the following properties:

Success: returns the result identifier, is a Boolean value, true / false (success / failure)

message: Description information, when an error occurs, you can fill in the error details here

Data: data, which is a generic type, can be an array or an object, etc., only when it is successful and requires data to be returned

ApiResultModel

The structural relationships are as follows:

 ResultModel
 └── ApiResultModel

The code attribute is added to this class, which is also a generic type. You can customize your return code type, which can be an integer or a string.

PageResultModel

The structural relationships are as follows:

 ResultModel
 └── PageResultModel

This class mainly returns results by paging, so the following properties have been added:

Total: total number of data bars, Long

size: number of bars per page, integer

Pages: total pages, Long

Current: current page, Long

Helper Tool Class

Help US manipulate entity classes. What helper s are there?The following:

ResultHelper

ResultHelper corresponds to ResultModel

success(String message)

Success, carry description information

success(String message, T data)

Success, with descriptive information and data

error(String message)

Error, with detailed description

ApiResultHelper

ApiResultHelper corresponds to ApiResultModel

success(S code, String message)

Success, carry return code and description information

success(S code, String message, T data)

Successfully, carry return codes, descriptions, and data

error(S code, String message)

Errors, carry error codes and detailed descriptions

PageResultHelper

PageResultHelper corresponds to PageResultModel

success(String message)

Success, carry description information

success(String message, T data)

Success, with descriptive information and data

success(String message, T data, long total, int size, long pages, long current)

Success, with description, data, total number, number of entries per page, total number of pages, current page

error(String message)

Error, with detailed description

quick get start

We provide you with three entity classes to satisfy different scenarios, ResultModel for returning results in general, ApiResultModel for interface development for returning results, and PageResultModel for returning results in paging.Each of these three entity classes has its own Helper, so you can use them directly to return.Of course, the recommended way to use it is to write a tool class for each Helper, then return through the tool class, which may make it more reasonable to customize your own return tool class.

Return with Helper

Let's start with a simple example code:

/**
 * Add Method Example
 * @return {@link ResultModel}
 */
@ApiOperation(value = "Add Method Example")
@PostMapping
public ResultModel<?> add() {
  return ResultHelper.success("Added Successfully");
}

Return results:

{
  "success": true,
  "message": "Added Successfully"
}

Note: This is only an example of an interface return, not that the add interface should be written like this.

Write Return Results Tool Class

For example, we could write a ResultUtils tool class to operate on ResultHelper.Examples include the following:

/**
 * Success examples
 * @return {@link ResultModel}
 */
public static ResultModel <?> success() {
    return ResultHelper.success("Success");
}

Using the Return Results tool class

We can call the methods in the ResultUtils class, as shown in the following example:

/**
* Success examples
* @return {@link ResultModel}
*/
@ApiOperation(value = "Success examples")
@DeleteMapping
public ResultModel<?> success() {
   return ResultUtils.success();
}

Impression results:

{
 "success": true,
 "message": "Success"
}

Use examples

Example Diagram

Test Interface Preview

Models

Return a successful result example

/**
 * Delete Method Example
 * @return {@link ResultModel}
 */
@ApiOperation(value = "Delete Method Example")
@DeleteMapping
public ResultModel<?> delete() {
    return ResultUtils.success();
}

Response results:

{
  "success": true,
  "message": "Success"
}

Return Failed Result Example

If something goes wrong, how do we get back?Let's take a look:

/**
 * Example Modification Method
 * @return {@link ResultModel}
 */
@ApiOperation(value = "Example Modification Method")
@PutMapping
public ResultModel<?> update() {
    return ResultUtils.error("Modification failed");
}

Return results:

{
  "success": false,
  "message": "Modification failed"
}

Return query result example

It is worth mentioning that this is the query method. Let's take a look

/**
 * Example query method
 * @return {@link ResultModel}
 */
@ApiOperation(value = "Example query method")
@GetMapping
public ResultModel<?> get() {
    List<Map<String, String>> list = new ArrayList<>();
    Map<String, String> map1 = new HashMap<>();

    map1.put("name", "Zhang Fei");
    map1.put("desc", "Swallow man Zhang Fei");
    list.add(map1);

    Map<String, String> map2 = new HashMap<>();
    map2.put("name", "Zhao Yun");
    map2.put("desc", "Changshan Zhao Zilong");
    list.add(map2);

    Map<String, String> map3 = new HashMap<>();
    map3.put("name", "Guan Yu");
    map3.put("desc", "Chopping Huaxiong with Warm Wine");
    list.add(map3);

    return ResultUtils.success(list);
}

Take a look at the response and see if it works as you like:

{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "Zhang Fei",
      "desc": "Swallow man Zhang Fei"
    },
    {
      "name": "Zhao Yun",
      "desc": "Changshan Zhao Zilong"
    },
    {
      "name": "Guan Yu",
      "desc": "Chopping Huaxiong with Warm Wine"
    }
  ]
}

Example of interface return data

/**
* Example of interface return data
* @return {@link ApiResultModel}
*/
@ApiOperation(value = "Example of interface return data")
@GetMapping("/api-data")
public ApiResultModel<Integer, ?> apiData() {
   return ApiResultUtils.success(getData());
}

Response results:

{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "Zhang Fei",
      "desc": "Swallow man Zhang Fei"
    },
    {
      "name": "Zhao Yun",
      "desc": "Changshan Zhao Zilong"
    },
    {
      "name": "Guan Yu",
      "desc": "Chopping Huaxiong with Warm Wine"
    }
  ],
  "code": 0
}

Example interface return failure result

/**
 * API Interface error return example
 * @return {@link ApiResultModel}
 */
@ApiOperation(value = "API Interface error return example")
@GetMapping("/api-error")
public ApiResultModel<Integer, ?> apiError() {
    return ApiResultUtils.error(1101, "API Interface error return example");
}

Response results:

{
  "success": false,
  "message": "API Interface error return example",
  "code": 1101
}

Paging Return Data Example

/**
 * Paging Return Data Example
 * @return {@link ApiResultModel}
 */
@ApiOperation(value = "Paging Return Data Example")
@GetMapping("/page")
public PageResultModel<?> page() {
    return PageResultUtils.success(getData(), 100, 10, 10, 1);
}

Response results:

{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "Zhang Fei",
      "desc": "Swallow man Zhang Fei"
    },
    {
      "name": "Zhao Yun",
      "desc": "Changshan Zhao Zilong"
    },
    {
      "name": "Guan Yu",
      "desc": "Chopping Huaxiong with Warm Wine"
    }
  ],
  "total": 100,
  "size": 10,
  "pages": 10,
  "current": 1
}

Tool class example

Return Results Tool Class

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.ResultHelper;
import com.fengwenyi.api_result.model.ResultModel;

/**
 * Return Results Encapsulation Tool Class
 * @author Erwin Feng[xfsy_2015@163.com]
 * @since 2019/11/30 13:54
 */
public class ResultUtils {

    /**
     *  Success
     * @return {@link ResultModel}
     */
    public static ResultModel <?> success() {
        return ResultHelper.success("Success");
    }

    /**
     *  Success, carrying data
     * @param data data
     * @param <T>  Type of data
     * @return {@link ResultModel}
     */
    public static <T> ResultModel <T> success(T data) {
        return ResultHelper.success("Success", data);
    }

    /**
     *  Errors, with detailed error description information
     * @param message Detailed error description information
     * @return {@link ResultModel}
     */
    public static ResultModel <?> error(String message) {
        return ResultHelper.error(message);
    }

}

API Interface Return Results Tool Class

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.ApiResultHelper;
import com.fengwenyi.api_result.model.ApiResultModel;

/**
 * API Interface Return Results Tool Class
 * @author Erwin Feng[xfsy_2015@163.com]
 * @since 2019/12/1 20:10
 */
public class ApiResultUtils {

    /**
     * Success, carry return code and description information
     * @return {@link ApiResultModel}
     */
    public static ApiResultModel<Integer, ?> success() {
        return ApiResultHelper.success(0, "Success");
    }

    /**
     * Successfully, carry return codes, descriptions, and data
     * @param data data
     * @param <T>  Type of data
     * @return {@link ApiResultModel}
     */
    public static <T> ApiResultModel<Integer, T> success(T data) {
        return ApiResultHelper.success(0, "Success", data);
    }

    /**
     * Error, carry error and detailed description
     * @param code Return code
     * @param message Believe Descriptive Information
     * @return {@link ApiResultModel}
     */
    public static ApiResultModel<Integer, ?> error(int code, String message) {
        return ApiResultHelper.error(code, message);
    }
}

Paging Return Results Tool Class

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.PageResultHelper;
import com.fengwenyi.api_result.model.PageResultModel;

/**
 * Paging Return Results Tool Class
 * @author Erwin Feng[xfsy_2015@163.com]
 * @since 2019/12/1 20:32
 */
public class PageResultUtils {

    /**
     * Success, carrying paging related data and information
     * @param data     data
     * @param total    Total number of data bars
     * @param size     Number of bars per page
     * @param pages    PageCount
     * @param current  Current Page
     * @param <T>      data type
     * @return {@link PageResultModel}
     */
    public static <T> PageResultModel<T> success(T data, long total, int size, long pages, long current) {
        return PageResultHelper.success("Success", data, total, size, pages, current);
    }

}

Sample Parse Return Results

To add this, let me give you my opinion on how to parse the returned JSON string.The string returned is a json-formatted string, and here I'm going to use fastjson to write an example of parsing.We usually encapsulate the request data as a generic method or tool class and simply return the data. Of course, if it fails or an exception occurs, it's all handled here.

Examples of common return result parsing

/**
 * Examples of parsing common return results
 * @return data
 */
public Object parseResult() {
    String result = "";
    ResultModel<?> resultModel = JSON.parseObject(result, ResultModel.class);
    Boolean success = resultModel.getSuccess();
    if (success != null && success) {
        return resultModel.getData();
    } else {
        // Exception Information
        String message = resultModel.getMessage();
        // exception handling
        throw new DataParseException(message);
    }
}

Interface Return Result Parsing Example

/**
 * Sample Parse Interface Return Results
 * @return data
 */
public Object parseApiResult() {
    String apiResult = "";
    ApiResultModel<?, ?> apiResultModel = JSON.parseObject(apiResult, ApiResultModel.class);
    Boolean success = apiResultModel.getSuccess();
    if (success != null && success) {
        return apiResultModel.getData();
    } else {
        Object code = apiResultModel.getCode();
        String message = apiResultModel.getMessage();
        // Processing based on interface error codes
        // ...
        return null;
    }
}

Paging Return Result Parsing Example

This is slightly different from the above, because some fields have been added, so we can use bean s to go back.

/**
 * Parse Paging Return Results Example
 * @return {@link PageResultDataBean}
 */
public PageResultDataBean parsePageResult() {
    String pageResult = "";
    PageResultModel<List<?>> pageResultModel = JSON.parseObject(pageResult, PageResultModel.class);
    Boolean success = pageResultModel.getSuccess();
    if (success != null && success) {
        List<?> data = pageResultModel.getData();
        Long total = pageResultModel.getTotal();
        Integer size = pageResultModel.getSize();
        Long pages = pageResultModel.getPages();
        Long current = pageResultModel.getCurrent();
        return new PageResultDataBean()
                .setTotal(total)
                .setSize(size)
                .setPages(pages)
                .setCurrent(current)
                .setData(data);
    } else {
        // Exception Information
        String message = pageResultModel.getMessage();
        // exception handling
        throw new DataParseException(message);
    }
}

Above all, is this what you want?Welcome to comment and let me know.

link

[1] api-result source | github

[2] api-result source | code cloud

[3] api-result central warehouse

[4] Test sample code

Topics: Java JSON Attribute github