I use Android Annotations to consume RESTful Web Services.
Client Side
Here is a sample REST API client
import org.androidannotations.annotations.rest.Accept;
import org.androidannotations.annotations.rest.Post;
import org.androidannotations.annotations.rest.Rest;
import org.androidannotations.api.rest.MediaType;
@Rest(rootUrl = Constants.Services.UserApi.ServiceBase, converters = {WorkbookHttpMessageConverter.class})
public interface UserApi {
@Post(Constants.Services.UserApi.ServiceMethods.PostUser)
@Accept(MediaType.APPLICATION_JSON)
OperationResult<User> postUser(SaveUserPostRequestModel model);
}
The key point here to set the expected date format is to provide your own converter class. As you can see, here I used my own converter class "WorkbookHttpMessageConverter" which is an extension to GsonHttpMessageConverter :
import com.adresyazilim.workbook.model.Constants;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import java.util.Date;
public class WorkbookHttpMessageConverter extends GsonHttpMessageConverter {
public WorkbookHttpMessageConverter() {
super(buildGson());
}
protected static Gson buildGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat(Constants.DateTimeConstants.DateTimeFormatString);
gsonBuilder.registerTypeAdapter(Date.class, new WorkbookJsonDateSerializer());
return gsonBuilder.create();
}
}
In my converter class, notice that I provided my own DateSerializer which implements both JsonSerializer<Date> and JsonDeserializer<Date>.
import com.adresyazilim.workbook.business.helper.DateTimeUtil;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Date;
public class WorkbookJsonDateSerializer implements JsonSerializer<Date>, JsonDeserializer<Date> {
@Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = (JsonObject)json;
String dateString = jsonObject.get("datetime").getAsString();
return DateTimeUtil.getDateTimeFromString(dateString);
}
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("datetime", DateTimeUtil.getDateTimeString(src));
return jsonObject;
}
}
You can implement DateSerializer and DateDeserializer instead of JsonSerializer and JsonDeserializer. If you do so, your date value will be serialized as a value, not a Json object. No big difference, do as you like. With the serialization strategy I provided here, my date values are serialized like the following.
{ "datetime" : "...." }
That's all you need to do at client side.
Server Side
At server side I used Spring-MVC. Below is a sample controller method :
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
IUserService userService;
@RequestMapping(value = "/save", method = RequestMethod.POST)
public OperationResult<User> saveUser(@Valid @RequestBody SaveUserPostRequestModel requestBody, BindingResult validationResult, HttpServletRequest request, HttpServletResponse response) {
...
}
}
The "SaveUserPostRequestModel" includes the User class inside it. Below I give the User class. Notice the annotations above the Date values.
import java.util.Date;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
public class User {
private String id;
private String username;
private String password;
@Size(min = 2, max = 20)
private String name;
@Size(min = 2, max = 20)
private String surname;
@Email
@NotNull
private String email;
private String photoUrl;
@JsonSerialize(using = WorkbookDateSerializer.class)
@JsonDeserialize(using = WorkbookDateDeserializer.class)
private Date lastUpdateTime;
}
I used JsonSerialize and JsonDeserialize annotations of "com.fasterxml.jackson" and provided my own serializer and deserializer classes.
The Deserializer
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@JacksonStdImpl
public class WorkbookDateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken token = jp.getCurrentToken();
if (token == JsonToken.START_OBJECT) {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
String dateString = node.get("datetime").asText();
return DateTimeUtil.getDateTimeFromString(dateString);
}
return null;
}
}
The Serializer
import java.io.IOException;
import java.util.Date;
import com.adresyazilim.workbook.backend.util.DateTimeUtil;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
@JacksonStdImpl
public class WorkbookDateSerializer extends DateSerializer {
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException {
jgen.writeStartObject();
jgen.writeStringField("datetime", DateTimeUtil.getDateTimeString(value));
jgen.writeEndObject();
}
}
This way I standardize and take control over the date format expected in the server side and the format sent from the client side.
Hiç yorum yok:
Yorum Gönder