Делая запрос GSON, используя залп

У меня есть следующий ответ 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"
        }
      ]
    }
  ]
}

Я создал следующие классы для запроса GSON. Как сделать запрос 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;
    }
}

Ответ 1

Просто создайте класс 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 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));
    }
}
} 

Теперь в вашем файле класса (Activity) просто вызовите этот класс следующим образом:

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

            queue.add(myReq);

Нам также нужно создать два метода -

  • createMyReqSuccessListener() - получить ответ от GsonRequest
  • createMyReqErrorListener() - для обработки любой ошибки

следующим образом:

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.
        }
    };
}

и

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

Надеюсь, это будет иметь смысл.

Ответ 2

Вот некоторые полезные фрагменты кода.

GsonRequest для запросов GET:

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 для петиций POST:

    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));
            }
        }
    }

Так вы используете его для объектов 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
                    );
        }

Так вы используете его для массивов JSON:

/**
     * Returns a dummy object 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
                );
    }

Так вы используете его для вызовов 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
                );
    }
}

Весь код взят отсюда, и у вас есть блог сообщение о том, как использовать OkHttp, Volley и Gson здесь.

Ответ 3

Я просто создал пользовательский запрос json, который основан на библиотеке Джексона вместо Gson.

Одна вещь, которую я хочу указать (мне потребовалось много часов, чтобы понять...): если вы хотите также поддерживать параметр POST Json, вы должны перейти от JsonRequest вместо Request. В противном случае ваше тело запроса Json будет закодировано в url, на стороне сервера вы не сможете преобразовать его обратно в java-объект.

Вот мой класс запроса json, который основан на Jackson и поддерживает параметр Json и заголовок:

    public class JacksonRequest<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 JacksonRequest(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 JacksonRequest(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;
        }
    }

}