Reputation: 73
I've come across a problem of using Gson library and generic types(my types and collections). However they have an answer how to solve this problem, I don't think it's appropriate to write a specific message converter for the every type I've already implemented and I'll implement.
What I did is:
Implemented my own message converter:
public class SuperHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
private final Charset charset;
private final Gson gson;
public CostomHttpMC_1(MediaType mediaType, String charset) {
super(mediaType);
this.charset = Charset.forName(charset);
gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
}
@Override
protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
String jsonString = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
return gson.fromJson(jsonString, clazz);
}
@Override
protected Long getContentLength(Object obj, MediaType contentType) {
try {
String jsonString = gson.toJson(obj);
return (long) jsonString.getBytes(charset.name()).length;
} catch (UnsupportedEncodingException ex) {
throw new InternalError(ex.getMessage());
}
}
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException {
String jsonString = gson.toJson(obj);
FileCopyUtils.copy(jsonString, new OutputStreamWriter(outputMessage.getBody(), charset));
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
It works well until I try to send a collection like List<String>
or some Type<T>
.
Gson has the solutions here: http://sites.google.com/site/gson/gson-user-guide
Also I tried the json-lib library yesterday. What I don't like about it is in-depth scanning of all objects which I have in the hierarchy. I tried to change the cycle detection strategy from CycleDetectionStrategy.STRICT
to CycleDetectionStrategy.LENIENT
, it didn't help at all!
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException {
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
String jsonString = JSONObject.fromObject( obj ).toString();
FileCopyUtils.copy(jsonString, new OutputStreamWriter(outputMessage.getBody(), charset));
}
Finally, a work-around for the generic collection's problem was found out: changing from ArrayList
to simple array helps to do serialization and deserialization. To be more specific you have to do it in a web-service, which you use in an application.
@RequestMapping(value = "/country/info/{code}")
public void info(@PathVariable("code") String code, Model model) {
//list
StuffImpl[] stuffList= new StuffImpl[0]; <-- this is the array I used!
stuffList= restTemplate.getForObject("http://localhost:8084/yourApp/restService/stuff", stuffList.getClass());
model.addAttribute("stuffList", stuffList);
}
So this approach is working good.
I failed to found out what a solution for generic type is. I really do hate an idea to write a new converter every time I implement a new generic type.
If you know any possible solution I'd appreciate your help a lot!
I'd be on the cloud nine if anyone could help me :)
L.
Upvotes: 2
Views: 3428
Reputation: 49341
There are some methods where you can pass java.lang.reflect.Type
. These methods are useful if the specified object is a generic type, e.g.:
Gson gson = new GsonBuilder().create();
List<String> names = new ArrayList<String>();
names.add("Foo");
names.add("Bar");
// marshal
String jsonLiteral = gson.toJson(names);
System.out.println(jsonLiteral);
// unmarshal
List<String> names2;
Type type = new TypeToken<List<String>>() {
}.getType();
names2 = gson.fromJson(jsonLiteral, type);
System.out.println(names2.get(0));
System.out.println(names2.get(1));
This will output:
["Foo","Bar"]
Foo
Bar
Upvotes: 1