Android 使用 volley 发出 GSON 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24537875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:23:26  来源:igfitidea点击:

making a GSON request using volley

androidjsongsonandroid-volley

提问by Abhay Sood

I have the following json response

我有以下 json 响应

{
  "tag": [
    {
      "listing_count": 5,
      "listings": [
        {
          "source": "source1",
          "data": {
            "image": "image1",
            "name": "name1"
          },
          "name": "name1"
        }
      ]
    },
    {
      "listing_count": 5,
      "listings": [
        {
          "source": "source2",
          "data": {
            "image": "imag2",
            "name": "name2"
          },
          "name": "name2"
        }
      ]
    }
  ]
}

I have created the following classes for GSON request. How do I make the GSON request and store the values for the response using a volley request. What should the GSON request be like?

我为 GSON 请求创建了以下类。如何使用 volley 请求发出 GSON 请求并存储响应值。GSON 请求应该是什么样的?

public class TagList {

ArrayList<Tag> tags;

public static class Tag {
    int listing_count;
    ArrayList<Listings> listings;

    public int getListing_count() {
        return listing_count;
    }

    public void setListing_count(int listing_count) {
        this.listing_count = listing_count;
    }

    public ArrayList<Listings> getListings() {
        return listings;
    }

    public void setListings(ArrayList<Listings> listings) {
        this.listings = listings;
    }

}

public static class Listings {
    String source;
    Data data;
    String name;

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

public static class Data {
    String image;
    String name;

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

回答by MSN

Just create a GsonRequestClass as follows (taken from Android Developer Docs)

只需GsonRequest按如下方式创建一个类(取自Android Developer Docs

public class GsonRequest<T> extends Request<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;

/**
 * Make a GET request and return a parsed object from JSON.
 *
 * @param url URL of the request to make
 * @param clazz Relevant class object, for Gson's reflection
 * @param headers Map of request headers
 */
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
        Listener<T> listener, ErrorListener errorListener) {
    super(Method.GET, url, errorListener);
    this.clazz = clazz;
    this.headers = headers;
    this.listener = listener;
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    return headers != null ? headers : super.getHeaders();
}

@Override
protected void deliverResponse(T response) {
    listener.onResponse(response);
}

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String json = new String(
                response.data,
                HttpHeaderParser.parseCharset(response.headers));
        return Response.success(
                gson.fromJson(json, clazz),
                HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JsonSyntaxException e) {
        return Response.error(new ParseError(e));
    }
}
} 

Now in your class file (Activity) just call the this class as follows:

现在在您的类文件(活动)中,只需按如下方式调用此类:

RequestQueue queue = MyVolley.getRequestQueue();
GsonRequest<MyClass> myReq = new GsonRequest<MyClass>(Method.GET,
                                                    "http://JSONURL/",
                                                    TagList.class,
                                                    createMyReqSuccessListener(),
                                                    createMyReqErrorListener());

            queue.add(myReq);

We also need to create two methods -

我们还需要创建两个方法——

  1. createMyReqSuccessListener()- receive the response from GsonRequest
  2. createMyReqErrorListener()- to handle any error
  1. createMyReqSuccessListener()- 收到来自 GsonRequest
  2. createMyReqErrorListener()- 处理任何错误

as follows:

如下:

private Response.Listener<MyClass> createMyReqSuccessListener() {
    return new Response.Listener<MyClass>() {
        @Override
        public void onResponse(MyClass response) {
           // Do whatever you want to do with response;
           // Like response.tags.getListing_count(); etc. etc.
        }
    };
}

and

private Response.ErrorListener createMyReqErrorListener() {
    return new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // Do whatever you want to do with error.getMessage();
        }
    };
}

I hope it will make some sense.

我希望它会有意义。

回答by Sotti

Here some useful code snippets.

这里有一些有用的代码片段。

GsonRequest for GET petitions:

GET 请求的 GsonRequest:

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;

/**
 * Convert a JsonElement into a list of objects or an object with Google Gson.
 *
 * The JsonElement is the response object for a {@link com.android.volley.Request.Method} GET call.
 *
 * @author https://plus.google.com/+PabloCostaTirado/about
 */
public class GsonGetRequest<T> extends Request<T>
{
    private final Gson gson;
    private final Type type;
    private final Response.Listener<T> listener;

    /**
     * Make a GET request and return a parsed object from JSON.
     *
     * @param url URL of the request to make
     * @param type is the type of the object to be returned
     * @param listener is the listener for the right answer
     * @param errorListener  is the listener for the wrong answer
     */
    public GsonGetRequest
    (String url, Type type, Gson gson,
     Response.Listener<T> listener, Response.ErrorListener errorListener)
    {
        super(Method.GET, url, errorListener);

        this.gson = gson;
        this.type = type;
        this.listener = listener;
    }

    @Override
    protected void deliverResponse(T response)
    {
        listener.onResponse(response);
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response)
    {
        try
        {
            String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));

            return (Response<T>) Response.success
                    (
                            gson.fromJson(json, type),
                            HttpHeaderParser.parseCacheHeaders(response)
                    );
        }
        catch (UnsupportedEncodingException e)
        {
            return Response.error(new ParseError(e));
        }
        catch (JsonSyntaxException e)
        {
            return Response.error(new ParseError(e));
        }
    }
}

GsonRequest for POST petitions:

POST 请求的 GsonRequest:

    import com.android.volley.NetworkResponse;
    import com.android.volley.ParseError;
    import com.android.volley.Response;
    import com.android.volley.toolbox.HttpHeaderParser;
    import com.android.volley.toolbox.JsonRequest;
    import com.google.gson.Gson;
    import com.google.gson.JsonSyntaxException;

    import java.io.UnsupportedEncodingException;
    import java.lang.reflect.Type;

    /**
     * Convert a JsonElement into a list of objects or an object with Google Gson.
     *
     * The JsonElement is the response object for a {@link com.android.volley.Request.Method} POST call.
     *
     * @author https://plus.google.com/+PabloCostaTirado/about
     */
    public class GsonPostRequest<T> extends JsonRequest<T>
    {
        private final Gson gson;
        private final Type type;
        private final Response.Listener<T> listener;

        /**
         * Make a GET request and return a parsed object from JSON.
         *
         * @param url URL of the request to make
         * @param type is the type of the object to be returned
         * @param listener is the listener for the right answer
         * @param errorListener  is the listener for the wrong answer
         */
        public GsonPostRequest
        (String url, String body, Type type, Gson gson,
         Response.Listener<T> listener, Response.ErrorListener errorListener)
        {
            super(Method.POST, url, body, listener, errorListener);

            this.gson = gson;
            this.type = type;
            this.listener = listener;
        }

        @Override
        protected void deliverResponse(T response)
        {
            listener.onResponse(response);
        }

        @Override
        protected Response<T> parseNetworkResponse(NetworkResponse response)
        {
            try
            {
                String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));

                return (Response<T>) Response.success
                        (
                                gson.fromJson(json, type),
                                HttpHeaderParser.parseCacheHeaders(response)
                        );
            }
            catch (UnsupportedEncodingException e)
            {
                return Response.error(new ParseError(e));
            }
            catch (JsonSyntaxException e)
            {
                return Response.error(new ParseError(e));
            }
        }
    }

This is how you use it for JSON objects:

这是您将它用于 JSON 对象的方式:

    /**
         * Returns a dummy object
         *
         * @param listener is the listener for the correct answer
         * @param errorListener is the listener for the error response
         *
         * @return @return {@link com.sottocorp.sotti.okhttpvolleygsonsample.api.GsonGetRequest}
         */
        public static GsonGetRequest<DummyObject> getDummyObject
        (
                Response.Listener<DummyObject> listener,
                Response.ErrorListener errorListener
        )
        {
            final String url = "http://www.mocky.io/v2/55973508b0e9e4a71a02f05f";

            final Gson gson = new GsonBuilder()
                    .registerTypeAdapter(DummyObject.class, new DummyObjectDeserializer())
                    .create();

            return new GsonGetRequest<>
                    (
                            url,
                            new TypeToken<DummyObject>() {}.getType(),
                            gson,
                            listener,
                            errorListener
                    );
        }

This is how you use it for JSON arrays:

这是将它用于 JSON 数组的方式:

/**
     * Returns a dummy object's array
     *
     * @param listener is the listener for the correct answer
     * @param errorListener is the listener for the error response
     *
     * @return {@link com.sottocorp.sotti.okhttpvolleygsonsample.api.GsonGetRequest}
     */
    public static GsonGetRequest<ArrayList<DummyObject>> getDummyObjectArray
    (
            Response.Listener<ArrayList<DummyObject>> listener,
            Response.ErrorListener errorListener
    )
    {
        final String url = "http://www.mocky.io/v2/5597d86a6344715505576725";

        final Gson gson = new GsonBuilder()
                .registerTypeAdapter(DummyObject.class, new DummyObjectDeserializer())
                .create();

        return new GsonGetRequest<>
                (
                        url,
                        new TypeToken<ArrayList<DummyObject>>() {}.getType(),
                        gson,
                        listener,
                        errorListener
                );
    }

This is how you use it for POST calls:

这是您将其用于 POST 调用的方式:

/**
     * An example call (not used in this example app) to demonstrate how to do a Volley POST call
     * and parse the response with Gson.
     *
     * @param listener is the listener for the success response
     * @param errorListener is the listener for the error response
     *
     * @return {@link com.sottocorp.sotti.okhttpvolleygsonsample.api.GsonPostRequest}
     */
    public static GsonPostRequest getDummyObjectArrayWithPost
            (
                    Response.Listener<DummyObject> listener,
                    Response.ErrorListener errorListener
            )
    {
        final String url = "http://PostApiEndpoint";
        final Gson gson = new GsonBuilder()
                .registerTypeAdapter(DummyObject.class, new DummyObjectDeserializer())
                .create();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("name", "Ficus");
        jsonObject.addProperty("surname", "Kirkpatrick");

        final JsonArray squareGuys = new JsonArray();
        final JsonObject dev1 = new JsonObject();
        final JsonObject dev2 = new JsonObject();
        dev1.addProperty("name", "Jake Wharton");
        dev2.addProperty("name", "Jesse Wilson");
        squareGuys.add(dev1);
        squareGuys.add(dev2);

        jsonObject.add("squareGuys", squareGuys);

        return new GsonPostRequest<>
                (
                        url,
                        jsonObject.toString(),
                        new TypeToken<DummyObject>()
                        {
                        }.getType(),
                        gson,
                        listener,
                        errorListener
                );
    }
}

All the code is taken from here, and you have a blog post about how to use OkHttp, Volley and Gson here.

所有代码均取自此处,您在此处一篇关于如何使用 OkHttp、Volley 和 Gson博客文章。

回答by cn123h

I just made a custom json request which is based on Hymanson library instead of Gson.

我刚刚提出了一个基于 Hymanson 库而不是 Gson 的自定义 json 请求。

One thing I want to point out (it took my many hours to figure out...): if you want to support POST Json parameter as well, you should extend from JsonRequest instead of Request. Otherwise your Json request body will be url-encoded, on the server side you cannot convert it back to java object.

我想指出的一件事(我花了好几个小时才弄明白……):如果你也想支持 POST Json 参数,你应该从 JsonRequest 而不是 Request 扩展。否则您的 Json 请求正文将被 url 编码,在服务器端您无法将其转换回 java 对象。

Here is my json request class, which is based on Hymanson and supports Json parameter and header:

这是我的 json 请求类,它基于 Hymanson 并支持 Json 参数和标头:

    public class HymansonRequest<ResponseType> extends JsonRequest<ResponseType> {

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final Class<ResponseType> responseClass;
    private final Map<String, String> headers;

    private String requestBody = null;
    private static final String PROTOCOL_CHARSET = "utf-8";

    /**
     * POST method without header
     */
    public HymansonRequest(String url,
                          Object parameterObject,
                          Class<ResponseType> responseClass,
                          Response.Listener<ResponseType> listener,
                          Response.ErrorListener errorListener) {

        this(Method.POST, url, null, parameterObject, responseClass, listener, errorListener);
    }

    /**
     * @param method see also com.android.volley.Request.Method
     */
    public HymansonRequest(int method,
                          String url,
                          Map<String, String> headers,
                          Object parameterObject,
                          Class<ResponseType> responseClass,
                          Response.Listener<ResponseType> listener,
                          Response.ErrorListener errorListener) {

        super(method, url, null, listener, errorListener);

        if (parameterObject != null)
            try {
                this.requestBody = objectMapper.writeValueAsString(parameterObject);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        this.headers = headers;
        this.responseClass = responseClass;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }

    @Override
    protected Response<ResponseType> parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            ResponseType result = objectMapper.readValue(json, responseClass);
            return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));

        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonMappingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonParseException e) {
            return Response.error(new ParseError(e));
        } catch (IOException e) {
            return Response.error(new ParseError(e));
        }
    }

    /**
     * Cannot call objectMapper.writeValueAsString() before super constructor, so override the same getBody() here.
     */
    @Override
    public byte[] getBody() {
        try {
            return requestBody == null ? null : requestBody.getBytes(PROTOCOL_CHARSET);
        } catch (UnsupportedEncodingException uee) {
            VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
                    requestBody, PROTOCOL_CHARSET);
            return null;
        }
    }

}