supereagle / experiences

Summary of practical experience in work.
2 stars 0 forks source link

Parse data from embedded generics in Java #27

Closed supereagle closed 7 years ago

supereagle commented 7 years ago

When design REST APIs, two points should be considered:

The response from ALL APIs with the same format, but with different fields (empty will be omitted in some case) and data type/struct. So we need to correctly parse the data from the response. Here is an example implemented in Java.

supereagle commented 7 years ago

User.java

package com.generic.demo;

public class User {
    private String username;
    private int age;
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

Result.java

package com.generic.demo;

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonProperty("message")
    private String msg;

    @JsonProperty("data")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T t;

    private long code;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String errorCode;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public long getCode() {
        return code;
    }

    public void setCode(long code) {
        this.code = code;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }
}
supereagle commented 7 years ago

EmbeddedGenericTest.java

package com.generic.demo;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class EmbeddedGenericTest {

    private final static Log LOGGER = LogFactory.getLog(EmbeddedGenericTest.class);

    protected final ObjectMapper mapper = new ObjectMapper();

    protected RestTemplate template = new RestTemplate();

    @Test
    public void testParseDataFromResponse() {
        String tokenUrl = "http://example.auth.com?username=robin";

        // Test GET request for user
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add("Authorization", "Basic abcdefg123456");
        HttpEntity<User> requestWithAuthorization = new HttpEntity<User>(null, headers);
        ResponseEntity<Result> response = template.exchange(tokenUrl, HttpMethod.GET, requestWithAuthorization,
                Result.class);

        // Check the response and parse user from it
        User user = EmbeddedGeneric.parseDataFromResponse(response, User.class);
        if (user == null) {
            Assert.fail("Fail to parse data from response");
        }
    }

    public <T> T parseDataFromResponse(ResponseEntity<Result> response, Class<T> dataType) {
        if (HttpStatus.OK != response.getStatusCode()) {
            LOGGER.error("Error: respose status code is no 200, as " + response.getStatusCode());
            return null;
        }

        if (response.getBody().getCode() != 0) {
            LOGGER.error("Error: respose code is not 0, as " + response.getStatusCode());
            return null;
        }

        try {
            return mapper.readValue(mapper.writeValueAsString(response.getBody().getT()), dataType);
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}