如何从Xero Java API的getContactsForHttpResponse获取XML响应体?
问题描述
我正在基于Xero Java API开展概念验证测试,希望获取HttpResponse的XML响应体。以下是我的代码(参考自Xero Java自定义连接启动项目),目前API使用自定义类加载Xero的数据,但我想拿到原始XML格式的响应体,尝试过类似contacts.getbody();的方式,请问有没有更优的方法?
import com.auth0.jwt.JWT; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import com.google.api.client.auth.oauth2.ClientCredentialsTokenRequest; import com.google.api.client.auth.oauth2.RefreshTokenRequest; import com.google.api.client.auth.oauth2.TokenResponse; import com.google.api.client.auth.oauth2.TokenResponseException; import com.google.api.client.http.BasicAuthentication; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.xero.api.ApiClient; import com.xero.api.client.AccountingApi; import com.xero.api.client.IdentityApi; import com.xero.models.identity.Connection; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class XeroConnection { private static final long serialVersionUID = 1L; final String clientId = "Myid"; final String clientSecret = "MySecret"; final String TOKEN_SERVER_URL = "https://identity.xero.com/connect/token"; final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); final JsonFactory JSON_FACTORY = new JacksonFactory(); private AccountingApi accountingApi; final static Logger logger = LoggerFactory.getLogger(XeroConnection.class); private String jwt_token = ""; private String access_token = ""; private String refresh_token = ""; private String expires_in_seconds = ""; private String xero_tenant_id = ""; public XeroConnection (){ } public void test() { ArrayList<String> scopeList = new ArrayList<String>(); scopeList.add("accounting.settings"); scopeList.add("accounting.transactions"); scopeList.add("accounting.contacts"); scopeList.add("accounting.journals.read"); scopeList.add("accounting.reports.read"); scopeList.add("accounting.attachments"); try { TokenResponse tokenResponse = new ClientCredentialsTokenRequest(HTTP_TRANSPORT, JSON_FACTORY, new GenericUrl(TOKEN_SERVER_URL)) .setScopes(scopeList) .setClientAuthentication( new BasicAuthentication(clientId, clientSecret)).execute(); System.out.println("Access token: " + tokenResponse.getAccessToken()); ApiClient defaultIdentityClient = new ApiClient("https://api.xero.com", null, null, null, null); IdentityApi idApi = new IdentityApi(defaultIdentityClient); List<Connection> connection = idApi.getConnections(tokenResponse.getAccessToken(),null); jwt_token = tokenResponse.toPrettyString(); access_token = tokenResponse.getAccessToken(); refresh_token = tokenResponse.getRefreshToken(); expires_in_seconds = tokenResponse.getExpiresInSeconds().toString(); xero_tenant_id = connection.get(0).getTenantId().toString(); // Check expiration of token and refresh if necessary String accessToken = checkToken(access_token,refresh_token); // Init AccountingApi client ApiClient defaultClient = new ApiClient(); // Get Singleton - instance of accounting client accountingApi = AccountingApi.getInstance(defaultClient); // Get All Contacts HttpResponse contacts = accountingApi.getContactsForHttpResponse(accessToken,xero_tenant_id,null, null, null, null, null, null, null); //contacts.getbody(); }catch (Exception e) { System.out.println(e.getMessage()); } } public String checkToken(String accessToken, String refreshToken) throws IOException { String currToken = null; try { DecodedJWT jwt = JWT.decode(accessToken); if (jwt.getExpiresAt().getTime() > System.currentTimeMillis()) { if (logger.isDebugEnabled()) { logger.debug( "------------------ Refresh Token : NOT NEEDED - return current token -------------------"); } currToken = accessToken; } else { if (logger.isDebugEnabled()) { logger.debug("------------------ Refresh Token : BEGIN -------------------"); } try { TokenResponse tokenResponse = new RefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(TOKEN_SERVER_URL), refreshToken) .setClientAuthentication(new BasicAuthentication(this.clientId, this.clientSecret)) .execute(); if (logger.isDebugEnabled()) { logger.debug("------------------ Refresh Token : SUCCESS -------------------"); } // DEMO PURPOSE ONLY - You'll need to implement your own token storage solution jwt_token = tokenResponse.toPrettyString(); access_token = tokenResponse.getAccessToken(); refresh_token = tokenResponse.getRefreshToken(); expires_in_seconds = tokenResponse.getExpiresInSeconds().toString(); currToken = tokenResponse.getAccessToken(); } catch (TokenResponseException e) { if (logger.isDebugEnabled()) { logger.debug("------------------ Refresh Token : EXCEPTION -------------------"); } if (e.getDetails() != null) { if (logger.isDebugEnabled()) { logger.debug("Error: " + e.getDetails().getError()); } if (e.getDetails().getErrorDescription() != null) { if (logger.isDebugEnabled()) { logger.debug(e.getDetails().getErrorDescription()); } } if (e.getDetails().getErrorUri() != null) { if (logger.isDebugEnabled()) { logger.debug(e.getDetails().getErrorUri()); } } } else { if (logger.isDebugEnabled()) { logger.debug("------------------ Refresh Token : EXCEPTION -------------------"); logger.debug(e.getMessage()); } } } } } catch (JWTDecodeException exception) { if (logger.isDebugEnabled()) { logger.debug("------------------ Refresh Token : INVALID TOKEN -------------------"); logger.debug(exception.getMessage()); } } return currToken; } }
解决方案
要获取Xero API返回的原始XML响应体,需先配置客户端接受XML格式,再通过输入流读取完整响应内容,具体实现如下:
1. 配置ApiClient接受XML
默认情况下Xero Java SDK优先使用JSON,需手动设置Accept请求头指定XML格式:
// 初始化ApiClient时添加默认头 ApiClient defaultClient = new ApiClient(); defaultClient.addDefaultHeader("Accept", "application/xml");
2. 读取原始XML响应体
通过HttpResponse.getContent()获取输入流,再转换为字符串,这比直接调用getBody()更可靠(getBody()可能已被SDK解析为Java对象):
// 获取Contacts的HttpResponse HttpResponse contactsResponse = accountingApi.getContactsForHttpResponse(accessToken, xero_tenant_id, null, null, null, null, null, null, null); // 读取并转换为XML字符串 String xmlResponse = ""; try (BufferedReader reader = new BufferedReader(new InputStreamReader(contactsResponse.getContent()))) { StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } xmlResponse = sb.toString(); // 输出或处理XML内容 System.out.println("原始XML响应:\n" + xmlResponse); } catch (IOException e) { logger.error("读取XML响应失败", e); }
注意事项
- 确保你的API权限(scope)包含对应资源的访问权限,否则会返回权限错误的XML
- 若需同时支持JSON和XML,可根据请求动态切换
Accept头 - 使用try-with-resources语法自动关闭输入流,避免资源泄漏
内容的提问来源于stack exchange,提问作者Juan Vallejo
相关产品推荐
相关产品推荐

