Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 48 additions & 18 deletions src/main/java/org/json/HTTP.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,36 +113,66 @@ public static JSONObject toJSONObject(String string) throws JSONException {
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
sb.append(jo.getString("HTTP-Version"));
sb.append(' ');
sb.append(jo.getString("Status-Code"));
sb.append(' ');
sb.append(jo.getString("Reason-Phrase"));
appendResponseHeader(sb, jo);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all changes to toString(). Refactoring this code is a judgement call. In this case, I trust Douglas Crockford's decision to include all HTTP string conversions in a single method.

} else if (jo.has("Method") && jo.has("Request-URI")) {
sb.append(jo.getString("Method"));
sb.append(' ');
sb.append('"');
sb.append(jo.getString("Request-URI"));
sb.append('"');
sb.append(' ');
sb.append(jo.getString("HTTP-Version"));
appendRequestHeader(sb, jo);
} else {
throw new JSONException("Not enough material for an HTTP header.");
}
sb.append(CRLF);
// Don't use the new entrySet API to maintain Android support

// Append other HTTP fields
appendAdditionalHeaders(sb, jo);

sb.append(CRLF);
return sb.toString();
}

/**
* Appends the HTTP response header to the StringBuilder.
* @param sb The StringBuilder to append to.
* @param jo The JSONObject representing the HTTP response.
* @throws JSONException if required fields are missing.
*/
private static void appendResponseHeader(StringBuilder sb, JSONObject jo) throws JSONException {
sb.append(jo.getString("HTTP-Version"));
sb.append(' ');
sb.append(jo.getString("Status-Code"));
sb.append(' ');
sb.append(jo.getString("Reason-Phrase"));
}

/**
* Appends the HTTP request header to the StringBuilder.
* @param sb The StringBuilder to append to.
* @param jo The JSONObject representing the HTTP request.
* @throws JSONException if required fields are missing.
*/
private static void appendRequestHeader(StringBuilder sb, JSONObject jo) throws JSONException {
sb.append(jo.getString("Method"));
sb.append(' ');
sb.append('"');
sb.append(jo.getString("Request-URI"));
sb.append('"');
sb.append(' ');
sb.append(jo.getString("HTTP-Version"));
}
/**
* Appends additional HTTP headers to the StringBuilder.
* @param sb The StringBuilder to append to.
* @param jo The JSONObject containing the additional headers.
*/
private static void appendAdditionalHeaders(StringBuilder sb, JSONObject jo) {
for (final String key : jo.keySet()) {
String value = jo.optString(key);
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
sb.append(key);
sb.append(": ");
sb.append(jo.optString(key));
sb.append(value);
sb.append(CRLF);
}
}
sb.append(CRLF);
return sb.toString();
}
}
40 changes: 20 additions & 20 deletions src/main/java/org/json/JSONObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,38 +201,38 @@ public JSONObject(JSONTokener x) throws JSONException {
/**
* Construct a JSONObject from a JSONTokener with custom json parse configurations.
*
* @param x
* @param jsonTokener
* A JSONTokener object containing the source string.
* @param jsonParserConfiguration
* Variable to pass parser custom configuration for json parsing.
* @throws JSONException
* If there is a syntax error in the source string or a
* duplicated key.
*/
public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
public JSONObject(JSONTokener jsonTokener, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this();
char c;
char currentChar;
String key;

if (x.nextClean() != '{') {
throw x.syntaxError("A JSONObject text must begin with '{'");
if (jsonTokener.nextClean() != '{') {
throw jsonTokener.syntaxError("A JSONObject text must begin with '{'");
}
for (;;) {
c = x.nextClean();
switch (c) {
currentChar = jsonTokener.nextClean();
switch (currentChar) {
case 0:
throw x.syntaxError("A JSONObject text must end with '}'");
throw jsonTokener.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
default:
key = x.nextSimpleValue(c).toString();
key = jsonTokener.nextSimpleValue(currentChar).toString();
}

// The key is followed by ':'.

c = x.nextClean();
if (c != ':') {
throw x.syntaxError("Expected a ':' after a key");
currentChar = jsonTokener.nextClean();
if (currentChar != ':') {
throw jsonTokener.syntaxError("Expected a ':' after a key");
}

// Use syntaxError(..) to include error location
Expand All @@ -241,10 +241,10 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration
// Check if key exists
boolean keyExists = this.opt(key) != null;
if (keyExists && !jsonParserConfiguration.isOverwriteDuplicateKey()) {
throw x.syntaxError("Duplicate key \"" + key + "\"");
throw jsonTokener.syntaxError("Duplicate key \"" + key + "\"");
}

Object value = x.nextValue();
Object value = jsonTokener.nextValue();
// Only add value if non-null
if (value != null) {
this.put(key, value);
Expand All @@ -253,21 +253,21 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration

// Pairs are separated by ','.

switch (x.nextClean()) {
switch (jsonTokener.nextClean()) {
case ';':
case ',':
if (x.nextClean() == '}') {
if (jsonTokener.nextClean() == '}') {
return;
}
if (x.end()) {
throw x.syntaxError("A JSONObject text must end with '}'");
if (jsonTokener.end()) {
throw jsonTokener.syntaxError("A JSONObject text must end with '}'");
}
x.back();
jsonTokener.back();
break;
case '}':
return;
default:
throw x.syntaxError("Expected a ',' or '}'");
throw jsonTokener.syntaxError("Expected a ',' or '}'");
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/org/json/JSONWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,7 @@ public static String valueToString(Object value) throws JSONException {
// Instead we will quote it as a string
return JSONObject.quote(numberAsString);
}
if (value instanceof Boolean || value instanceof JSONObject
|| value instanceof JSONArray) {
if (isDirectlyConvertibleToJSON(value)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert this change. A separate method is not needed for this conditional. You can add a clarification comment if you want.

return value.toString();
}
if (value instanceof Map) {
Expand All @@ -349,6 +348,10 @@ public static String valueToString(Object value) throws JSONException {
return JSONObject.quote(value.toString());
}

private static boolean isDirectlyConvertibleToJSON(Object value) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General rule: All methods must include JavaDoc comment

return value instanceof Boolean || value instanceof JSONObject || value instanceof JSONArray;
}

/**
* Append either the value <code>true</code> or the value
* <code>false</code>.
Expand Down
Loading