Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow sending any JSON with JsonArrayRequest and JsonObjectRequest #419

Open
jpd236 opened this issue Jul 1, 2021 · 1 comment
Open
Milestone

Comments

@jpd236
Copy link
Collaborator

jpd236 commented Jul 1, 2021

Prior to #406, JsonArrayRequest required JSONArray request bodies, and JsonObjectRequest required JSONObject request bodies. Nothing should couple the request type and response type, so it's reasonable to want to send JSONObjects and get back JSONArray, or vice versa. However, the new constructors can end up breaking compilation of existing code which depend on Volley, since the request argument is nullable and thus ambiguous if null is provided. For example, code like:

JsonObjectRequest request = new JsonObjectRequest(Method.POST, url, null, listener, errorListener);

compiles fine with the current Volley production release, but suddenly fails to compile here since the compiler doesn't know whether this corresponds to the JSONObject or JSONArray constructor.

I don't see a great, backwards-compatible fix for this. Adding a factory method or builder isn't sufficient because subclassing the request is fairly common too (e.g. to populate custom headers). We could just reorder the arguments in one of them, but that would just make for a more confusing API.

So I think for the short term, we should just revert back to what was in place before. Longer term, if/when we make breaking API changes, we can consider improvements here.

The workaround is to extend JsonRequest directly, e.g.:

public class MyJsonObjectRequest extends JsonRequest<JSONObject> {
    public MyJsonObjectRequest(..., JSONArray request, ...) {
        super(..., request != null ? request.toString() : null, ...);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString =
                    new String(
                            response.data,
                            HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
            return Response.success(
                    new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }
}

or just avoid using these classes entirely - they're not that complex, and you're probably better off using a strongly-typed JSON object instead.

@jpd236 jpd236 added this to the 2.0.0 milestone Jul 1, 2021
jpd236 added a commit to jpd236/volley that referenced this issue Jul 1, 2021
These conflict with pre-existing constructors - since the request argument is nullable, existing code which passes in null requests is no longer invoking an unambiguous constructor.

See google#419 for more details and a workaround.

These constructors were added in google#406 and have not yet been included in a public release, so they are safe to remove.
jpd236 added a commit to jpd236/volley that referenced this issue Jul 1, 2021
These conflict with pre-existing constructors - since the request argument is nullable, existing code which passes in null requests is no longer invoking an unambiguous constructor.

See google#419 for more details and a workaround.

These constructors were added in google#406 and have not yet been included in a public release, so they are safe to remove.
jpd236 added a commit to jpd236/volley that referenced this issue Jul 1, 2021
These conflict with pre-existing constructors - since the request argument is nullable, existing code which passes in null requests is no longer invoking an unambiguous constructor.

See google#419 for more details and a workaround.

These constructors were added in google#406 and have not yet been included in a public release, so they are safe to remove.
jpd236 added a commit that referenced this issue Jul 7, 2021
…420)

These conflict with pre-existing constructors - since the request argument is nullable, existing code which passes in null requests is no longer invoking an unambiguous constructor.

See #419 for more details and a workaround.

These constructors were added in #406 and have not yet been included in a public release, so they are safe to remove.
@SushmitSingh
Copy link

SushmitSingh commented Oct 16, 2023

You Can Create Cstm

Here JSONArray posting And in response a JsonObject

`import androidx.annotation.Nullable;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;

/**
 * A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an
 * optional {@link JSONArray} to be passed in as part of the request body.
 */
public class JsonArrayToObjectRequest extends JsonRequest<JSONObject> {

    /**
     * Creates a new request.
     *
     * @param url URL to fetch the JSON from
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public JsonArrayToObjectRequest(
            String url, Listener<JSONObject> listener, @Nullable ErrorListener errorListener) {
        super(Method.GET, url, null, listener, errorListener);
    }

    /**
     * Creates a new request.
     *
     * @param method the HTTP method to use
     * @param url URL to fetch the JSON from
     * @param jsonRequest A {@link JSONArray} to post with the request. Null indicates no parameters
     *     will be posted along with the request.
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public JsonArrayToObjectRequest(
            int method,
            String url,
            @Nullable JSONArray jsonRequest,
            Listener<JSONObject> listener,
            @Nullable ErrorListener errorListener) {
        super(
                method,
                url,
                jsonRequest != null ? jsonRequest.toString() : null,
                listener,
                errorListener);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString =
                    new String(
                            response.data,
                            HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
            return Response.success(
                    new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }
}
`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants