return 根据参数的通用列表类型
return generic list type according the parameter
我正在从 Web 服务获取数据。我想创建一个通用方法来发出请求,并根据我作为参数传递的类型转换输出。让我们看看代码:
public <T> Class getAPI(URL url, Class <T> clazz)
{
// GET
ObjectMapper mapper = new ObjectMapper();
List<clazz> objs = mapper.readValue(url, new TypeReference<List<clazz>>(){});
return objs;
}
还没有成功...
可能吗?
编辑
我是这样调用方法的:
URL url = new URL("http://localhost:8080/...");
Util u = new Util();
List<className> objs = u.getAPI(url, className.class);
System.out.println(className.get(0).getId());
ClassCastException 的堆栈跟踪
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to pkg.className
at GetTest.test(GetTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
你快明白了:
public <T> List<T> getAPI(URL url, Class <T> clazz)
{
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, new TypeReference<List<T>>(){});
return objs;
}
没有测试,但是用 T
替换 clazz
并使 return 类型为 List<T>
(因为你想要一个列表作为结果)应该可以诀窍。
终于。做了一些研究,现在它按我们的需要工作了(抱歉,这个对我来说很私人[在这里插入愤怒的表情符号])
神奇之处在于:
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, TypeFactory.defaultInstance().constructParametrizedType(ArrayList.class, List.class, clazz));
return objs;
}
这里是完整的代码(测试数据还是一样的):
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
public class Util {
// Just as posted by prior post:
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, TypeFactory.defaultInstance().constructParametrizedType(ArrayList.class, List.class, clazz));
return objs;
}
// Test all together
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
Util u = new Util();
List<TestData> objs = u.getAPI(url, TestData.class);
System.out.println(objs.get(0).getId());
}
}
--- 不是那么原创 post ---
好吧,我想我又失败了一次......事实上,泛型工作正常,但 Jackson 不喜欢我们的泛型,正如这里指出的:
第二种方法可能是一个很好的起点,但是当我尝试这个时,我的类路径中没有 TypeFactory.genericType()
,可能是错误的 jackson-version...
下面的截图没问题,直到你让SysOut运行,它和你上面提到的ClassCastException
一起崩溃(多么尴尬...)
---原版post---
所以给你:
import java.io.IOException;
import java.net.URL;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Util {
// exactly like posted in my prior answer (despite exceptionhandling):
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, new TypeReference<List<T>>(){});
return objs;
}
// Test all together
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
// thanks for this URL!
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
Util u = new Util();
List<TestData> objs = u.getAPI(url, TestData.class);
System.out.println(objs.get(0).getId());
}
}
我使用的TestData
PoJo:
public class TestData {
private String name, email, body;
private int postId, id;
// generated by IDE, i'm lazy AF
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public int getPostId() {
return postId;
}
public void setPostId(int postId) {
this.postId = postId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
结果((编辑:不!!)足够好,我猜):
我正在从 Web 服务获取数据。我想创建一个通用方法来发出请求,并根据我作为参数传递的类型转换输出。让我们看看代码:
public <T> Class getAPI(URL url, Class <T> clazz)
{
// GET
ObjectMapper mapper = new ObjectMapper();
List<clazz> objs = mapper.readValue(url, new TypeReference<List<clazz>>(){});
return objs;
}
还没有成功...
可能吗?
编辑
我是这样调用方法的:
URL url = new URL("http://localhost:8080/...");
Util u = new Util();
List<className> objs = u.getAPI(url, className.class);
System.out.println(className.get(0).getId());
ClassCastException 的堆栈跟踪
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to pkg.className
at GetTest.test(GetTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
你快明白了:
public <T> List<T> getAPI(URL url, Class <T> clazz)
{
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, new TypeReference<List<T>>(){});
return objs;
}
没有测试,但是用 T
替换 clazz
并使 return 类型为 List<T>
(因为你想要一个列表作为结果)应该可以诀窍。
终于。做了一些研究,现在它按我们的需要工作了(抱歉,这个对我来说很私人[在这里插入愤怒的表情符号])
神奇之处在于:
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, TypeFactory.defaultInstance().constructParametrizedType(ArrayList.class, List.class, clazz));
return objs;
}
这里是完整的代码(测试数据还是一样的):
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
public class Util {
// Just as posted by prior post:
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, TypeFactory.defaultInstance().constructParametrizedType(ArrayList.class, List.class, clazz));
return objs;
}
// Test all together
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
Util u = new Util();
List<TestData> objs = u.getAPI(url, TestData.class);
System.out.println(objs.get(0).getId());
}
}
--- 不是那么原创 post ---
好吧,我想我又失败了一次......事实上,泛型工作正常,但 Jackson 不喜欢我们的泛型,正如这里指出的:
第二种方法可能是一个很好的起点,但是当我尝试这个时,我的类路径中没有 TypeFactory.genericType()
,可能是错误的 jackson-version...
下面的截图没问题,直到你让SysOut运行,它和你上面提到的ClassCastException
一起崩溃(多么尴尬...)
---原版post---
所以给你:
import java.io.IOException;
import java.net.URL;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Util {
// exactly like posted in my prior answer (despite exceptionhandling):
public <T> List<T> getAPI(URL url, Class <T> clazz) throws JsonParseException, JsonMappingException, IOException {
// GET
ObjectMapper mapper = new ObjectMapper();
List<T> objs = mapper.readValue(url, new TypeReference<List<T>>(){});
return objs;
}
// Test all together
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
// thanks for this URL!
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
Util u = new Util();
List<TestData> objs = u.getAPI(url, TestData.class);
System.out.println(objs.get(0).getId());
}
}
我使用的TestData
PoJo:
public class TestData {
private String name, email, body;
private int postId, id;
// generated by IDE, i'm lazy AF
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public int getPostId() {
return postId;
}
public void setPostId(int postId) {
this.postId = postId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
结果((编辑:不!!)足够好,我猜):