package no.bouvet.jsonclient;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class JsonConverter {
private final String CONTENT_TYPE_JSON = "application/json";
private ObjectMapper objectMapper;
public JsonConverter() {
objectMapper = new JsonClientObjectMapper();
}
public JsonConverter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public void registerModule(Module module) {
objectMapper.registerModule(module);
}
public <T> T toObject(HttpEntity entity, Class<T> clz) {
try {
String entityStr = EntityUtils.toString(entity);
if(entityStr != null && !entityStr.isEmpty()) {
return toObject(entityStr, clz);
}
return null;
} catch (Exception e) {
throw new RuntimeException(getToObjectError(entity, clz, "object"), e);
} finally {
EntityUtils.consumeQuietly(entity);
}
}
public <T> List<T> toList(HttpEntity entity, Class<T> clz) {
try {
String entityStr = EntityUtils.toString(entity);
if(entityStr != null && !entityStr.isEmpty()) {
return toList(entityStr, clz);
}
return null;
} catch (Exception e) {
throw new RuntimeException(getToObjectError(entity, clz, "list"), e);
} finally {
EntityUtils.consumeQuietly(entity);
}
}
public <T> List<List<T>> toListOfList(HttpEntity entity, Class<T> clz) {
try {
String entityStr = EntityUtils.toString(entity);
if(entityStr != null && !entityStr.isEmpty()) {
return toListOfList(entityStr, clz);
}
return null;
} catch (Exception e) {
throw new RuntimeException(getToObjectError(entity, clz, "list of list"), e);
} finally {
EntityUtils.consumeQuietly(entity);
}
}
public <T> Map<String, T> toMap(HttpEntity entity, Class<T> clz) {
try {
String entityStr = EntityUtils.toString(entity);
if(entityStr != null && !entityStr.isEmpty()) {
return toMap(entityStr, clz);
}
return null;
} catch (Exception e) {
throw new RuntimeException(getToObjectError(entity, clz, "map"), e);
} finally {
EntityUtils.consumeQuietly(entity);
}
}
public String toJson(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException("Error when converting " + object.getClass() + " to json", e);
}
}
public <T> T toObject(String json, Class<T> clz) {
try {
return objectMapper.readValue(json, clz);
} catch (IOException e) {
throw new RuntimeException("Error when converting json to " + clz, e);
}
}
public <T> List<T> toList(String json, Class<T> clz) {
try {
return objectMapper.readValue(json, getTypeFactory().constructParametricType(List.class, clz));
} catch (IOException e) {
throw new RuntimeException("Error when converting json to List<" + clz + ">", e);
}
}
public <T> List<List<T>> toListOfList(String json, Class<T> clz) {
try {
return objectMapper.readValue(json, getTypeFactory().constructParametricType(List.class, getTypeFactory().constructParametricType(List.class, clz)));
} catch (IOException e) {
throw new RuntimeException("Error when converting json to List<" + clz + ">", e);
}
}
public <T> Map<String, T> toMap(String json, Class<T> clz) {
try {
return objectMapper.readValue(json, new TypeReference<Map<String, T>>(){});
} catch (IOException e) {
throw new RuntimeException("Error when converting json to Map<String, " + clz + ">", e);
}
}
private TypeFactory getTypeFactory() {
return objectMapper.getTypeFactory();
}
private <T> String getToObjectError(HttpEntity entity, Class<T> clz, String type) {
String error = "Error when parsing response entity to " + type + " of " + clz + ". ";
if (!isContentTypeJson(entity)) {
error += "Content Type should be '" + CONTENT_TYPE_JSON + "' but was '" + getContentType(entity) + "'";
}
return error;
}
private boolean isContentTypeJson(HttpEntity entity) {
if (getContentType(entity).contains(CONTENT_TYPE_JSON)) {
return true;
}
return false;
}
private String getContentType(HttpEntity entity) {
return entity.getContentType().getValue();
}
}