001package com.box.sdk; 002 003import com.box.sdk.http.ContentType; 004import com.eclipsesource.json.Json; 005import com.eclipsesource.json.JsonObject; 006import com.eclipsesource.json.ParseException; 007import java.io.IOException; 008import java.io.InputStreamReader; 009import java.util.List; 010import java.util.Map; 011 012/** 013 * Used to read HTTP responses containing JSON from the Box API. 014 * 015 * <p>This request type extends BoxAPIResponse to provide additional functionality for handling JSON strings. It reads 016 * the response body into a string and allows the JSON in the response to be logged.</p> 017 */ 018public class BoxJSONResponse extends BoxAPIResponse { 019 private static final int BUFFER_SIZE = 8192; 020 private JsonObject jsonObject; 021 022 /** 023 * Constructs a BoxJSONResponse without an associated HttpURLConnection. 024 */ 025 public BoxJSONResponse() { 026 super(); 027 } 028 029 BoxJSONResponse(BoxAPIResponse response) { 030 this( 031 response.getResponseCode(), 032 response.getRequestMethod(), 033 response.getRequestUrl(), 034 response.getHeaders(), 035 new JsonObject() 036 ); 037 } 038 039 /** 040 * Constructs a BoxAPIResponse with an http response code and response body. 041 * 042 * @param responseCode http response code 043 * @param headers map of http headers 044 * @param body response body as Json Object 045 */ 046 public BoxJSONResponse(int responseCode, 047 String requestMethod, 048 String requestUrl, 049 Map<String, List<String>> headers, 050 JsonObject body 051 ) { 052 super(responseCode, requestMethod, requestUrl, headers, body.toString(), ContentType.APPLICATION_JSON); 053 this.jsonObject = body; 054 } 055 056 /** 057 * Get response as Json Object. 058 * 059 * @return response as JsonObject 060 */ 061 public JsonObject getJsonObject() { 062 if (this.jsonObject != null) { 063 return this.jsonObject; 064 } else { 065 return Json.parse(this.getJSON()).asObject(); 066 } 067 } 068 069 /** 070 * Gets the body of the response as a JSON string. When this method is called, the response's body will be read and 071 * the response will be disconnected, meaning that the stream returned by {@link #getBody} can no longer be used. 072 * 073 * @return the body of the response as a JSON string. 074 */ 075 public String getJSON() { 076 if (this.jsonObject != null) { 077 return this.jsonObject.toString(); 078 } else if (this.getBody() == null) { 079 return null; 080 } else { 081 InputStreamReader reader = new InputStreamReader(this.getBody(), StandardCharsets.UTF_8); 082 StringBuilder builder = new StringBuilder(); 083 char[] buffer = new char[BUFFER_SIZE]; 084 085 try { 086 int read = reader.read(buffer, 0, BUFFER_SIZE); 087 while (read != -1) { 088 builder.append(buffer, 0, read); 089 read = reader.read(buffer, 0, BUFFER_SIZE); 090 } 091 092 this.close(); 093 reader.close(); 094 } catch (IOException e) { 095 throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); 096 } 097 String jsonAsString = builder.toString(); 098 try { 099 this.jsonObject = Json.parse(jsonAsString).asObject(); 100 } catch (ParseException e) { 101 throw new RuntimeException("Error parsing JSON:\n" + jsonAsString, e); 102 } 103 return jsonAsString; 104 } 105 } 106 107 @Override 108 protected String bodyToString() { 109 String bodyString = super.bodyToString(); 110 if (bodyString == null) { 111 return this.getJSON(); 112 } else { 113 return bodyString; 114 } 115 } 116}