Skip to content

Commit deeb294

Browse files
zeynepsuZeynep Karasozen
andauthored
fix: handle arrays in error response (#2017)
* fix: handle arrays in error response * Address feedback Co-authored-by: Zeynep Karasozen <[email protected]>
1 parent 12c8f64 commit deeb294

File tree

3 files changed

+123
-1
lines changed

3 files changed

+123
-1
lines changed

aws-android-sdk-core/src/main/java/com/amazonaws/http/JsonErrorResponseHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public static JsonErrorResponse fromResponse(HttpResponse response) throws IOExc
190190
int statusCode = response.getStatusCode();
191191

192192
// parse error body
193-
Map<String, String> map = JsonUtils.jsonToMap(new BufferedReader(new InputStreamReader(
193+
Map<String, String> map = JsonUtils.jsonToStringMapWithList(new BufferedReader(new InputStreamReader(
194194
response.getContent(), StringUtils.UTF8)));
195195

196196
/*

aws-android-sdk-core/src/main/java/com/amazonaws/util/json/JsonUtils.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,87 @@ public static Map<String, String> jsonToMap(String json) {
141141
return jsonToMap(new StringReader(json));
142142
}
143143

144+
/**
145+
* Convenient method to convert a JSON string to a map. Arrays
146+
* are not discarded, they are read into the value as a string.
147+
* Number and boolean are also stored as string.
148+
* Nested arrays are not supported.
149+
*
150+
* @param in reader
151+
* @return a non null, unmodifiable, string to string map
152+
*/
153+
@SuppressWarnings("unchecked")
154+
public static Map<String, String> jsonToStringMapWithList(Reader in) {
155+
AwsJsonReader reader = getJsonReader(in);
156+
try {
157+
// in case it's empty
158+
if (reader.peek() == null) {
159+
return Collections.EMPTY_MAP;
160+
}
161+
Map<String, String> map = new HashMap<String, String>();
162+
reader.beginObject();
163+
while (reader.hasNext()) {
164+
String key = reader.nextName();
165+
if (reader.isContainer()) {
166+
if (AwsJsonToken.BEGIN_ARRAY.equals(reader.peek())) {
167+
final StringWriter out = new StringWriter();
168+
final AwsJsonWriter writer = getJsonWriter(out);
169+
reader.beginArray();
170+
writer.beginArray();
171+
try {
172+
while (!AwsJsonToken.END_ARRAY.equals(reader.peek())) {
173+
AwsJsonToken nextToken = reader.peek();
174+
if (AwsJsonToken.BEGIN_OBJECT.equals(nextToken)){
175+
reader.beginObject();
176+
writer.beginObject();
177+
} else if (AwsJsonToken.FIELD_NAME.equals(nextToken)){
178+
String name = reader.nextName();
179+
// do not write key if the value is a nested array
180+
if (!AwsJsonToken.BEGIN_ARRAY.equals(reader.peek())) {
181+
writer.name(name);
182+
}
183+
} else if (AwsJsonToken.END_OBJECT.equals(nextToken)){
184+
reader.endObject();
185+
writer.endObject();
186+
} else if (AwsJsonToken.END_ARRAY.equals(nextToken)) {
187+
reader.endArray();
188+
writer.endArray();
189+
} else if (AwsJsonToken.VALUE_STRING.equals(nextToken)
190+
|| AwsJsonToken.VALUE_NUMBER.equals(nextToken)
191+
|| AwsJsonToken.VALUE_NULL.equals(nextToken)
192+
|| AwsJsonToken.VALUE_BOOLEAN.equals(nextToken)) {
193+
String value = reader.nextString();
194+
writer.value(value);
195+
}
196+
else {
197+
// skip non string nodes inside the array
198+
reader.skipValue();
199+
}
200+
}
201+
} catch (IOException e) {
202+
e.printStackTrace();
203+
}
204+
reader.endArray();
205+
writer.endArray();
206+
writer.flush();
207+
writer.close();
208+
map.put(key, out.toString());
209+
} else {
210+
// skip non string or non array nodes
211+
reader.skipValue();
212+
}
213+
} else {
214+
map.put(key, reader.nextString());
215+
}
216+
}
217+
reader.endObject();
218+
reader.close();
219+
return Collections.unmodifiableMap(map);
220+
} catch (IOException e) {
221+
throw new AmazonClientException("Unable to parse JSON String.", e);
222+
}
223+
}
224+
144225
/**
145226
* Encode a string to string map as a JSON string.
146227
*

aws-android-sdk-core/src/test/java/com/amazonaws/util/json/JsonUtilsTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ public class JsonUtilsTest {
4444
+ "\"object\":{}"
4545
+ "}";
4646

47+
private static final String JSON_STRING_WITH_ARRAYS = "{\"string\":\"string\","
48+
+ "\"long\":123,"
49+
+ "\"double\":123.45,"
50+
+ "\"null\":null,"
51+
+ "\"true\":true,"
52+
+ "\"false\":false,"
53+
+ "\"encoding\":\"Chloë\","
54+
+ "\"array\":[\"string\",123,123.45,null,true,false],"
55+
+ "\"array2\":[{\"key1\":\"string1\"},{\"key2\":\"string2\"}],"
56+
+ "\"array3\":[{\"key1\":123.45},{\"key2\":false}],"
57+
+ "\"array4\":[\"string\",123,[\"string\",123,123.45,null,true,false],123.45,null,true],"
58+
+ "\"array5\":[{\"key1\":\"string1\"},{\"key2\":[{\"key3\":\"string2\"}]},{\"key3\":\"string3\"}],"
59+
+ "\"array6\":[[],[[]]],"
60+
+ "\"array7\":[],"
61+
+ "\"array8\":[null],"
62+
+ "\"array9\":[\"A\",{\"B\":[[]]},\"C\",[[]],\"D\",null],"
63+
+ "\"object\":{}"
64+
+ "}";
4765
@Test
4866
public void testJsonToMap() {
4967
Map<String, String> map = JsonUtils.jsonToMap(JSON_STRING);
@@ -58,6 +76,29 @@ public void testJsonToMap() {
5876
assertNull("object is ignored", map.get("object"));
5977
}
6078

79+
@Test
80+
public void testJsonToMapWithList() {
81+
Map<String, String> map = JsonUtils.jsonToStringMapWithList(new StringReader(JSON_STRING_WITH_ARRAYS));
82+
Map<String, String> actualMap = new HashMap<>();
83+
actualMap.put("string", "string");
84+
actualMap.put("long", "123");
85+
actualMap.put("double", "123.45");
86+
actualMap.put("null", null);
87+
actualMap.put("true", "true");
88+
actualMap.put("false", "false");
89+
actualMap.put("encoding", "Chloë");
90+
actualMap.put("array", "[\"string\",\"123\",\"123.45\",null,\"true\",\"false\"]");
91+
actualMap.put("array2", "[{\"key1\":\"string1\"},{\"key2\":\"string2\"}]");
92+
actualMap.put("array3", "[{\"key1\":\"123.45\"},{\"key2\":\"false\"}]");
93+
actualMap.put("array4", "[\"string\",\"123\",\"123.45\",null,\"true\"]");
94+
actualMap.put("array5", "[{\"key1\":\"string1\"},{},{\"key3\":\"string3\"}]");
95+
actualMap.put("array6", "[]");
96+
actualMap.put("array7", "[]");
97+
actualMap.put("array8", "[null]");
98+
actualMap.put("array9", "[\"A\",{},\"C\",\"D\",null]");
99+
assertEquals(actualMap, map);
100+
}
101+
61102
@Test
62103
public void testMapToJson() {
63104
Map<String, String> source = new HashMap<String, String>();

0 commit comments

Comments
 (0)