Android Study's thorough solution to Gson parsing exception: com.google.gson.JsonSyntaxException

Keywords: Attribute JSON Google Java

LZ-Say: The wind blew like a prelude to the goblin's arrival.

Preface

In the process of development, most of the parameters that App usually receives are in JSON format, so there are many ways to parse json. The Android side uses Gson relatively more. In the process of parsing, if you encounter the normative background, you can rest assured that casual waves, But, if you encounter the God background, then, ha-ha you. I really can't imagine what problems will arise...

Describing problems

Implement a function, call an interface, and return the following parameters:

{
  "areaName": null,
  "accountId": 138,
  "accountName": null,
  "accountNumber": null,
  "msgCode": "",
  "msg": "",
  "pname": "Zhao Chun Sheng",
  "nation": "19701010",
  "imgUri": null,
  "phone": "15831345807",
  "areaCode": "230303",
  "usedTime": null,
  "collectionWay": 1,
  "registTime": null,
  "createTime": "2017-10-26 06:46:23",
  "amount": 580,
  "price": 0,
  "certificates": null,
  "certificatesPhotos": null
}

Everyone carefully observes, glance at it, there is no problem is not it?

In the process of parsing, GG is...

Traffic pit road, super-divine Road

Confident code, running, app prompts the following types of errors:

com.google.gson.JsonSyntaxException

Look up, Json format is wrong? Look back carefully at the returned Json.

Some values are null and others are ""

Combining Du Niang's opinions and reviewing Json string, it is determined that the failure of parsing is caused by the irregular return of background interface parameters (i.e., unreasonable design).

So how to solve it?

In fact, in the process of transformation and parsing, we can effectively deal with the illegal attribute fields returned from the background to Json. Look directly at the following tool classes.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class GsonUtil {

    /**
     * Time String Conversion Time Object for Formatting
     */
    private static final String DATEFORMAT_default = "yyyy-MM-dd HH:mm:ss";

    /**
     * Deserialize using the default gson object
     *
     * @param json
     * @param typeToken
     * @return
     */
    public static <T> T fromJsonDefault(String json, TypeToken<T> typeToken) {
        Gson gson = new Gson();
        return gson.fromJson(json, typeToken.getType());
    }

    /**
     * json String-to-list or map
     *
     * @param json
     * @param typeToken
     * @return
     */
    public static <T> T fromJson(String json, TypeToken<T> typeToken) {
        Gson gson = new GsonBuilder()
                // Deserialization of rewritten map
                .registerTypeAdapter(new TypeToken<Map<String, Object>>() {
                }.getType(), new MapTypeAdapter()).create();
        return gson.fromJson(json, typeToken.getType());
    }

    /**
     * json String Rotation bean Object
     *
     * @param json
     * @param cls
     * @return
     */
    public static <T> T fromJson(String json, Class<T> cls) {
        Gson gson = new GsonBuilder().setDateFormat(DATEFORMAT_default)
                .create();
        return gson.fromJson(json, cls);
    }

    /**
     * Object to json
     *
     * @param obj
     * @param format
     * @return
     */
    public static String toJson(Object obj, boolean format) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        //  Set the default time format
        gsonBuilder.setDateFormat(DATEFORMAT_default);
        // Add formatting settings
        if (format) {
            gsonBuilder.setPrettyPrinting();
        }
        Gson gson = gsonBuilder.create();
        return gson.toJson(obj);
    }

    public static class MapTypeAdapter extends TypeAdapter<Object> {

        @Override
        public Object read(JsonReader in) throws IOException {
            JsonToken token = in.peek();
            switch (token) {
                case BEGIN_ARRAY:
                    List<Object> list = new ArrayList<Object>();
                    in.beginArray();
                    while (in.hasNext()) {
                        list.add(read(in));
                    }
                    in.endArray();
                    return list;
                case BEGIN_OBJECT:
                    Map<String, Object> map = new LinkedTreeMap<String, Object>();
                    in.beginObject();
                    while (in.hasNext()) {
                        map.put(in.nextName(), read(in));
                    }
                    in.endObject();
                    return map;
                case STRING:
                    return in.nextString();
                case NUMBER:
                    // Rewrite the processing logic of the number, divide the number value into integer type and floating-point type.
                    double dbNum = in.nextDouble();
                    // The number exceeds the maximum of long, returning the floating-point type
                    if (dbNum > Long.MAX_VALUE) {
                        return dbNum;
                    }
                    // Judging whether a number is an integer value
                    long lngNum = (long) dbNum;
                    if (dbNum == lngNum) {
                        return lngNum;
                    } else {
                        return dbNum;
                    }
                case BOOLEAN:
                    return in.nextBoolean();
                case NULL:
                    in.nextNull();
                    return null;
                default:
                    throw new IllegalStateException();
            }
        }

        @Override
        public void write(JsonWriter out, Object value) throws IOException {
            // Serialization does not require implementation
        }

    }

}

The invocation method is as follows:

List<SearchResultBean> resultBean = GsonUtil.fromJson(
        GsonUtil.toJson(result.getData(), true),  // Here you need to format the acquired json again
        new TypeToken<List<SearchResultBean>>() {
        });

End

In fact, Du Niang has Du Niang's benefits.

Many developers, including LZ, belong to Baidu Developer, but there is nothing to be proud of.

What we can do is to enrich ourselves on the way forward, ladies and gentlemen.

Posted by t_miller_3 on Mon, 17 Dec 2018 23:06:04 -0800