package io.kaif.web.support; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * <p> * a convenient wrapper when you return single value in JSON. Example use cases are: * </p> * <p> * 1. your method return an integer: * <p> * <pre> * public SingleWrapper<Integer> count() { * return SingleWrapper.of("count", 12); * } * * // return is like {"count":12} * </pre> * <p> * 2. your method return a String, this case is most useful because if not using wrapper, string * returned will not be double quoted even using application/json content-type * <p> * <pre> * public SingleWrapper<String> mark() { * return SingleWrapper.of("correct"); * } * * // return is like {"data":"correct"} * </pre> * <p> * 3. your method return a single nullable POJO, not collection. if the POJO is null, the response * will become empty body (0 byte). this make parsing harder and client don't know what the * meaning of empty response body (success? fail?). * <p> * <pre> * public SingleWrapper<Pojo> findByXxx() { * return SingleWrapper.of(null); * } * * // return is like {"data":null} * </pre> * <p> * of course, you don't need to apply SingleWrapper to a POJO that never be null. */ @JsonSerialize(using = SingleWrapperSerializer.class) public class SingleWrapper<T> { private static final long serialVersionUID = 68220190832499715L; /** * wrapped value in "data" field * <p> * <pre> * { * "data":value * } * </pre> */ public static <T> SingleWrapper<T> of(T value) { return new SingleWrapper<>("data", value); } /** * wrapped value in custom field name * <p> * <pre> * { * "myFieldName":value * } * </pre> */ public static <T> SingleWrapper<T> of(T value, String fieldName) { return new SingleWrapper<>(fieldName, value); } private final String fieldName; private final T value; private SingleWrapper(String fieldName, T value) { this.fieldName = fieldName; this.value = value; } public String getFieldName() { return fieldName; } public T getValue() { return value; } } class SingleWrapperSerializer extends JsonSerializer<SingleWrapper<?>> { @Override public void serialize(SingleWrapper<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeStartObject(); jgen.writeObjectField(value.getFieldName(), value.getValue()); jgen.writeEndObject(); } }