I don't know if it clear for you, i want to implement a method that like SpringMVC @RequestBody() do, this method can deserialize input json string to object, and this method should support complex object type(like List<List>)
Now using Java reflection and Jackson, we can easily deserialize List, such as "[1,100]" to List, but if the input is "[[1,100]]", there is nested list in another list.
Show my code:
// there is a class and method's parameter has annotation @Param
class Code{
public void getName(@Param("fooList") List<List<Long>> fooList) {
System.out.println("getName run");
}
}
// reflection Code#getName and deserialize method
public Object inject(Parameter param) {
Object object = null;
try {
Class<?> paramType = param.getType();
Param paramAnnotation = param.getAnnotation(Param.class);
// for unit test purpose, hard code json string here
object = "[[1,3]]";
if (object != null) {
if (Collection.class == paramType || List.class.isAssignableFrom(paramType)) {
// basic type
if (clazz != null) {
// todo: string to list, need support complex List
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(text,
objectMapper.getTypeFactory().constructCollectionType(List.class,
clazz));
} catch (Exception e) {
throw new SDKException("");
}
List list = JSONs.toList(object.toString(), clazz);
List converterArgs = new ArrayList<>(list.size());
for (Object arg : list) {
try {
arg = Casts.cast(clazz, arg);
} catch (Exception e) {
throw new InvalidParametersException("type error");
}
converterArgs.add(arg);
}
object = converterArgs;
}
}
if (String.class.isAssignableFrom(paramType)) {
object = JSONs.string(object);
} else {
if (!object.getClass().equals(paramType)) {
try {
object = Casts.cast(paramType, object);
} catch (Exception e) {
throw new InvalidParametersException("type error");
}
}
}
}
} catch (Exception e) {
throw new SDKException("", e);
}
return object;
}
@Test
public void testReflection() {
try {
Method getName = Code.class.getMethod("getName", List.class);
Parameter[] parameters = getName.getParameters();
AnnotationParamInjector injector = new AnnotationParamInjector();
Object inject = injector.inject(parameters[0]);
System.out.println("inject = " + inject);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
Backgroud: i want to implement method like SpringMVC controller, so we need to deserialize method parameter to object, now we only support normal class and List but don't support complex List.
Questions: Java reflection can parse generic class, even complex List, we can get reflect List from outer to inner, but how can i parse json string "[[1, 100]]", this is what i'm solving.
Show my pseudocode as below, recursive call constructClass to get it's generic row type, after call constructClass(), the json string should be parse, such as "[[1,100]]" change to "[1,100]", and good solution to do this?
public void constructClass(String text, Class<?> clazz) {
Type type = clazz.getGenericSuperclass();
if (Collection.class == clazz || List.class.isAssignableFrom(clazz)) {
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Type genericType = pType.getActualTypeArguments()[0];
this.constructClass(text, genericType.getClass());
}
} else if (Map.class == clazz) {
} else {
}
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
pType.getActualTypeArguments()[0]
}
}
Aucun commentaire:
Enregistrer un commentaire