#java #spring-boot #rest #spring-mvc
#java #spring-boot #rest #spring-mvc
Вопрос:
Вот мой код:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("xx","xx");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<String> response = new RestTemplate().postForEntity( url, request ,String.class);
Вот мой ответ:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body onLoad="xx">
<form action='xxx' method="post" name="aspForm" >
<input type="hidden" name="responseMessage" value='Successfully Registered'/>
<input type="hidden" name="url" value='xxxx'/>
<input type="hidden" name="status" value='SUCCESS'/>
</form>
</body>
</html>
Как преобразовать эти пары имен и значений из html-ответа в JSON?
Комментарии:
1. Почему бы вам не внести изменения в службу, чтобы возвращать json вместо html
2. Это немного «облегченное» объяснение, чтобы полностью понять цель здесь. Если вы пытаетесь отправить JSON
String
со.html
страницы обратно на сервер, к которому вы подключаетесь, существуют сотни ответов SO об отправке JSON от клиента на сервер. Извините, надеюсь, я не кажусь грубым, это не мое намерение… Я не могу точно сказать, какую часть (и где) необходимо преобразовать в ваши данные.3. Дорогой иностранец, когда я захожу в сторонний API с указанным выше form_url_encoded, я получаю указанный выше HTML-ответ. Мне нужно получить ответ и выполнить некоторые бизнес-операции. Надеюсь, теперь вы поняли.
4. Уважаемый @Y2020-09, приведенное ниже решение — это то, которое я ищу.
Ответ №1:
Этого можно достичь с помощью Jsoup и Jackson object mapper:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
Document doc = Jsoup.parse(html);
String responseMessage = doc.body()
.getElementsByAttributeValue("name", "responseMessage")
.first()
.attributes()
.get("value");
String status = doc.body()
.getElementsByAttributeValue("name", "status")
.first()
.attributes()
.get("value");
String url = doc.body()
.getElementsByAttributeValue("name", "url")
.first()
.attributes()
.get("value");
Response response = new Response();
response.setResponseMessage(responseMessage);
response.setStatus(status);
response.setUrl(url);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(response);
System.out.println(json);
Вывод:
{"responseMessage":"Successfully Registered","status":"SUCCESS","url":"xxxx"}
Обновить:
Если необходимо преобразовать строку HTML без ручного вебскрейпинга, это также возможно (но, я полагаю, будет работать только для XHTML, потому что синтаксический анализатор сломается при разметке, не совместимой с XML).
Зависимость от POM:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.5.2</version>
<type>jar</type>
</dependency>
Определение компонента (пропущен getter / setter):
@XmlRootElement(name = "html")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlPath("body/form/input[@name='url']/@value")
private String url;
@XmlPath("body/form/input[@name='status']/@value")
private String status;
@XmlPath("body/form/input[@name='responseMessage']/@value")
private String responseMessage;
}
Создать конвертер сообщений:
private static HttpMessageConverter<Object> createXmlHttpMessageConverter() throws JAXBException {
MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
// I added lot of mediatypes, leave necessary ones
xmlConverter.setSupportedMediaTypes(Arrays.asList(
MediaType.APPLICATION_XML, MediaType.TEXT_HTML, MediaType.TEXT_PLAIN, MediaType.TEXT_XML
));
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setClassesToBeBound(Response.class);
// without this jaxb will complain about doctype in the beginning
jaxb2Marshaller.setSupportDtd(true);
xmlConverter.setMarshaller(jaxb2Marshaller);
xmlConverter.setUnmarshaller(jaxb2Marshaller);
return xmlConverter;
}
Инициализация шаблона REST:
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(0, createXmlHttpMessageConverter());
Также вам нужно будет установить MOXy в качестве поставщика JAXB. Я использовал для этого кода
System.setProperty(JAXBContext.JAXB_CONTEXT_FACTORY, "org.eclipse.persistence.jaxb.JAXBContextFactory");
но это можно сделать и другими способами.
Все это позволит вам выполнить вызов:
Response response = rest.postForEntity(url, request, Response.class);
И из экземпляра ответа должно быть тривиально получить JSON с помощью Jackson.
Комментарии:
1. Да, Александра, я согласен с вашим ответом. Мы можем сделать то же самое, также используя объект HtmlPage в HtmlUnit framework. Предоставленный вами код — это не что иное, как «Webscraping». Есть ли какой-либо другой способ, которым мы можем перехватить HTML-ответ от API к JSON? Спасибо 🙂
2. Обновленный ответ с другим решением
3. ваши усилия высоко ценятся.. спасибо, мой друг .. 🙂