使用Spring RestTemplate获取JSON对象列表

我有两个问题:

  • 如何使用Spring RestTemplate映射JSON对象列表。
  • 如何映射嵌套的JSON对象。

我正在尝试使用https://bitpay.com/api/rates,通过遵循来自http://spring.io/guides/gs/consuming-rest/的教程。

505179 次浏览

也许这样……

ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(urlGETList, Object[].class);
Object[] objects = responseEntity.getBody();
MediaType contentType = responseEntity.getHeaders().getContentType();
HttpStatus statusCode = responseEntity.getStatusCode();

RequestMapping的控制器代码

@RequestMapping(value="/Object/getList/", method=RequestMethod.GET)
public @ResponseBody List<Object> findAllObjects() {


List<Object> objects = new ArrayList<Object>();
return objects;
}
ResponseEntityHttpEntity的扩展,它添加了一个HttpStatus状态码。在RestTemplate@Controller方法中使用。 在RestTemplate中,这个类由getForEntity()exchange()返回

对我来说这很有效

Object[] forNow = template.getForObject("URL", Object[].class);
searchList= Arrays.asList(forNow);

Object是你想要的类的位置

我从这个帖子https://jira.spring.io/browse/SPR-8263找到了工作。

基于这篇文章,你可以返回一个类似这样的列表:

ResponseEntity<? extends ArrayList<User>> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<User>>)ArrayList.class, userId);

首先定义一个对象来保存返回数组的实体。如。

@JsonIgnoreProperties(ignoreUnknown = true)
public class Rate {
private String name;
private String code;
private Double rate;
// add getters and setters
}

然后你可以使用该服务并通过以下方式获得一个强类型列表:

ResponseEntity<List<Rate>> rateResponse =
restTemplate.exchange("https://bitpay.com/api/rates",
HttpMethod.GET, null, new ParameterizedTypeReference<List<Rate>>() {
});
List<Rate> rates = rateResponse.getBody();

上面的其他解决方案也可以工作,但我喜欢得到一个强类型列表,而不是Object[]。

经过多次测试,这是我发现的最好的方法:)

Set<User> test = httpService.get(url).toResponseSet(User[].class);

这就是你所需要的

public <T> Set<T> toResponseSet(Class<T[]> setType) {
HttpEntity<?> body = new HttpEntity<>(objectBody, headers);
ResponseEntity<T[]> response = template.exchange(url, method, body, setType);
return Sets.newHashSet(response.getBody());
}

我在这里遇到的最大问题是构建将RestTemplate匹配到兼容类所需的Object结构。幸运的是,我找到了http://www.jsonschema2pojo.org/(在浏览器中获得JSON响应并将其作为输入),我不能充分推荐这个!

如果你更喜欢一个pojo列表,一种方法是这样做的:

class SomeObject {
private int id;
private String name;
}


public <T> List<T> getApi(final String path, final HttpMethod method) {
final RestTemplate restTemplate = new RestTemplate();
final ResponseEntity<List<T>> response = restTemplate.exchange(
path,
method,
null,
new ParameterizedTypeReference<List<T>>(){});
List<T> list = response.getBody();
return list;
}

像这样使用它:

 List<SomeObject> list = someService.getApi("http://localhost:8080/some/api",HttpMethod.GET);

以上的解释可以在这里找到(https://www.baeldung.com/spring-rest-template-list),并在下面解释。

在上面的代码中发生了一些事情。首先,我们使用ResponseEntity作为返回类型,用它来包装我们真正需要的对象列表。其次,我们调用了RestTemplate.exchange()而不是getForObject()。

这是使用RestTemplate的最通用方式。它要求我们指定HTTP方法、可选请求体和响应类型。在本例中,我们为响应类型使用ParameterizedTypeReference的匿名子类。

最后一部分允许我们将JSON响应转换为适当类型的对象列表。当我们创建ParameterizedTypeReference的匿名子类时,它使用反射来捕获关于我们希望将响应转换为的类类型的信息。

它使用Java的Type对象保存这些信息,我们不再需要担心类型擦除。

考虑看看这个答案,特别是如果你想在List中使用泛型 Spring RestTemplate和泛型类型ParameterizedTypeReference集合,如List<T> < / p >

实际上,我之前为我的一个项目开发了一些功能,以下是代码:

/**
* @param url             is the URI address of the WebService
* @param parameterObject the object where all parameters are passed.
* @param returnType      the return type you are expecting. Exemple : someClass.class
*/


public static <T> T getObject(String url, Object parameterObject, Class<T> returnType) {
try {
ResponseEntity<T> res;
ObjectMapper mapper = new ObjectMapper();
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setConnectTimeout(2000);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<T> entity = new HttpEntity<T>((T) parameterObject, headers);
String json = mapper.writeValueAsString(restTemplate.exchange(url, org.springframework.http.HttpMethod.POST, entity, returnType).getBody());
return new Gson().fromJson(json, returnType);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}


/**
* @param url             is the URI address of the WebService
* @param parameterObject the object where all parameters are passed.
* @param returnType      the type of the returned object. Must be an array. Exemple : someClass[].class
*/
public static <T> List<T> getListOfObjects(String url, Object parameterObject, Class<T[]> returnType) {
try {
ObjectMapper mapper = new ObjectMapper();
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setConnectTimeout(2000);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<T> entity = new HttpEntity<T>((T) parameterObject, headers);
ResponseEntity<Object[]> results = restTemplate.exchange(url, org.springframework.http.HttpMethod.POST, entity, Object[].class);
String json = mapper.writeValueAsString(results.getBody());
T[] arr = new Gson().fromJson(json, returnType);
return Arrays.asList(arr);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

我希望这能帮助到别人!

你可以为每个条目创建POJO,

class BitPay{
private String code;
private String name;
private double rate;
}

然后使用BitPay列表的ParameterizedTypeReference,你可以使用:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<List<Employee>> response = restTemplate.exchange(
"https://bitpay.com/api/rates",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<BitPay>>(){});
List<Employee> employees = response.getBody();

在我的情况下,我更喜欢提取一个字符串,然后使用JsonNode接口浏览上下文

    var response =  restTemplate.exchange("https://my-url", HttpMethod.GET, entity,  String.class);
if (response.getStatusCode() == HttpStatus.OK) {
var jsonString = response.getBody();
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonString);
        

System.out.println(actualObj);
}

或者很快

ObjectNode actualObj= restTemplate.getForObject("https://my-url", ObjectNode.class);

然后读取内部数据与路径表达式,即。

boolean b = actualObj.at("/0/states/0/no_data").asBoolean();

作为一个通用模块,Page<?>对象可以像JodaModuleLog4jJsonModule等一样被module反序列化。参考我的回答

这里提到了3种检索对象列表的方法。所有这些都将完美地工作

@RequestMapping(value = "/emp2", produces = "application/json")
public List<Employee> getEmp2()
{
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<Employee>> response = restTemplate.exchange(
"http://hello-server/rest/employees", HttpMethod.GET,entity,
new ParameterizedTypeReference<List<Employee>>() {});
return response.getBody();
}

(或)

@RequestMapping(value = "/emp3", produces = "application/json")
public List<Employee> getEmp3()
{
Employee[] empArray = restTemplate.getForObject("http://hello-server/rest/employees", Employee[].class);
List<Employee> emp= Arrays.asList(empArray);
return emp;
}

(或)

    @RequestMapping(value = "/emp4", produces = "application/json")
public Employee[] getEmp4()
{
ResponseEntity<Employee[]> responseEntity = restTemplate.getForEntity("http://hello-server/rest/employees", Employee[].class);
Employee[] empList = responseEntity.getBody();
//MediaType contentType = responseEntity.getHeaders().getContentType();
//HttpStatus statusCode = responseEntity.getStatusCode();
return  empList;
}

Employee.class

public class Employee {


private Integer id;
private String name;
private String Designation;
private String company;


//getter setters and toString()


}
< p > 更简单的方法: < br > 我将向你们展示Authorization heard和without Authorization header:

    <李> 未经授权:
    一。进行依赖注入(构造函数注入): 你也可以选择字段注入。
public class RestTemplateService {
private final RestTemplate template;
public RestTemplateService(RestTemplate template) {
this.template = template;
}
}

b。调用getList()方法:

public ResponseEntity<List> getResponseList(String url, HttpMethod type) {
return template.exchange(url, type, new HttpEntity<>(new HttpHeaders()), List.class);
}
  1. 我喜欢小方法。所以我把这些功能分开:
 public ResponseEntity<List> getResponse(String url, HttpMethod type) {
return template.exchange(url, type, getRequest(getHeaders(USERNAME, PASS)), List.class);
}


private HttpEntity<String> getRequest(HttpHeaders headers) {
return new HttpEntity<>(headers);
}


private HttpHeaders getHeaders(String username, String password) {
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + new String(Base64.encodeBase64((username + ":" + password).getBytes())));
return headers;
}


希望问题会得到解决!

对于那些使用Spring + Kotlin的人来说,下面是翻译:

val rates = restTemplate.exchange("https://bitpay.com/api/rates", HttpMethod.GET, null, object : ParameterizedTypeReference<List<Rate>>() {}).body!!