Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GSON avoid the JsonSyntaxException return the partial mapping

I'm getting this issue, I do not want to solve that issue but find to way to say to GSON "skip errors and continue" parsing :

Can't parses json : java.lang.IllegalStateException: 
    Expected a string but was BEGIN_OBJECT at line 1 column 16412

Code used:

JsonReader reader = new JsonReader(new StringReader(data));
reader.setLenient(true);
Articles articles = gson.create().fromJson(reader, Articles.class);

The data are (to simplify) : Articles->Pages->medias.fields. One field in the current error is defined as string but I'm receiving an object (but again it is only one occurrence). I cannot add protection everywhere so my question is: "is there a skip and continues in GSON ?

I want to avoid JsonSysntaxException with GSON when there is an issue on a node and I expect at least to retrieve the partial data parsed. In my case I would have had 99.999% of the data and only my wrong field as null… I know it seems not clean, but I would enable the "strict mode" for unit test or continous integration to detect problem and on production I would enable a "soft mode" so my application could start (even when the server side doing errors). I cannot say to my custom, your app cannot start because an article has an invalide data.

Is GSON have a "skip and continue on error" ?

like image 826
Nicolas Lauquin Avatar asked Jun 27 '13 10:06

Nicolas Lauquin


2 Answers

Here is the solution: You have to create TypeAdapterFactory which will allow you to intercept default TypeAdapter, but still leave to you access to default TypeAdapter as a delegate. Then you can just try to read value using delegate from default TypeAdapter and process unexpected data as you wish.

      public Gson getGson() {

                return new GsonBuilder()
                            .registerTypeAdapterFactory(new LenientTypeAdapterFactory())
                .create();
            }


        class LenientTypeAdapterFactory implements TypeAdapterFactory {

                public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

                    final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

                    return new TypeAdapter<T>() {

                        public void write(JsonWriter out, T value) throws IOException {
                            delegate.write(out, value);
                        }

                        public T read(JsonReader in) throws IOException {
                            try { //Here is the magic
//Try to read value using default TypeAdapter
                                return delegate.read(in); 
                            } catch (JsonSyntaxException e) {
//If we can't in case when we expecting to have an object but array is received (or some other unexpected stuff), we just skip this value in reader and return null
                                in.skipValue(); 
                                return null;
                            }
                        }
                    };
                }
    }
like image 51
Dmitry Avatar answered Oct 28 '22 02:10

Dmitry


I think that the answer is simply: no, generally it can't.

Due to the recursive parsing nature of the library if something is wrong, it would throw some kind of exception. It would interesting if you could post a SSCCE of your problem to experiment if it is possible to create a customized type adapter that handle better exceptions.

like image 25
giampaolo Avatar answered Oct 28 '22 02:10

giampaolo