当前位置:网站首页>Several ways of gson's @jsonadapter annotation

Several ways of gson's @jsonadapter annotation

2022-07-01 06:29:00 ydfind

summary

You can customize TypeAdapter and TypeAdapterFactory The way , Customize gson Serialization and deserialization rules for ,TypeAdapterFactory You can get the context gson、TokenType type ;

Or by inheritance JsonReader Rewrite the code , stay beginArray and endArray Try to skip array Of string Form left and right Double quotes ", gson.fromJson(myJsonReader, Type) It can also be realized When parsing, it will automatically String Turn into List, But with annotations @JsonAdapter In a more formal way ;

Problem description

json character string :

{
    "cityIds": "[1,2,1001,13131]",
    "types": "[{\"name\": \"biz\",\"details\": [1]}]"
}

java Object definitions :

 @Data
    public static class RequestParams {
       // json The string corresponds to String
        private List<TypeItem> types;
        private List<Integer> cityIds;
    }
    @Data
    public static class TypeItem {
        private String name;
        private List<Integer> details;
    }

You can see json Inside cityIds and types All are String, and pojo Inside, it is List, Use gson Of fromJson take json To pojo There will be an error

Mode one


  @JsonAdapter(StringCollectionTypeAdapterFactory.class)
     private List<TagItem> tags;
     @JsonAdapter(StringCollectionTypeAdapterFactory.class)
     private List<Integer> cityIds;

public static class StringCollectionTypeAdapterFactory implements TypeAdapterFactory {
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
            //  in order to write Can be used when elementTypeAdapter
            Type type = typeToken.getType();
            Class<? super T> rawType = typeToken.getRawType();
            if (!Collection.class.isAssignableFrom(rawType)) {
                return null;
            }
            Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
            TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
            
            TypeAdapter<T> result = new Adapter(gson, elementTypeAdapter, typeToken);
            return result;
        }

        private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
            private final TypeAdapter<E> elementTypeAdapter;
            private final Gson gson;
            private final TypeToken listType;

            public Adapter(Gson context, TypeAdapter<E> elementTypeAdapter, TypeToken listType) {
                this.elementTypeAdapter = elementTypeAdapter;
                this.gson = context;
                this.listType = listType;
            }

            @Override public Collection<E> read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }

                List<E> list = gson.fromJson(in.nextString(), listType.getType());
                return list;
            }
 
            // write Then you can put array Of string Format , Become... Again array
            @Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
                if (collection == null) {
                    out.nullValue();
                    return;
                }

                out.beginArray();
                for (E element : collection) {
                    elementTypeAdapter.write(out, element);
                }
                out.endArray();
            }
        }
    }

Mode two -write Original sample

public static class StringCollectionTypeAdapterFactory1 implements TypeAdapterFactory {

        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
            return new Adapter(gson, typeToken);
        }

        private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
            private final Gson gson;
            private final TypeToken listType;

            public Adapter(Gson context, TypeToken listType) {
                this.gson = context;
                this.listType = listType;
            }

            @Override public Collection<E> read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }

                List<E> list = gson.fromJson(in.nextString(), listType.getType());
                return list;
            }

            @Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
                if (collection == null) {
                    out.nullValue();
                    return;
                }

                out.value(gson.toJson(collection));
            }
        }
    }

Mode three - Simple writing

private static class CollectionStringTypeAdapterFactory implements TypeAdapterFactory {
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            return new TypeAdapter<T>() {
                @Override
                public void write(JsonWriter out, T value) throws IOException {
                    if (value == null) {
                        out.nullValue();
                        return;
                    }
                    gson.getAdapter(type).write(out, value);
                }

                @Override
                public T read(JsonReader in) throws IOException {
                    if (in.peek() == JsonToken.NULL) {
                        return null;
                    }
                    if (in.peek() == JsonToken.BEGIN_ARRAY) {
                        return gson.getAdapter(type).read(in);
                    }
                    T collection = gson.fromJson(in.nextString(), type.getType());
                    return collection;
                }
            };
        }
    }

The test cases are as follows :

@Test
    public void testGson1() {
        Gson gson = new Gson();
        RequestParams requestParam;
        String json;
        // 1. Automatically put string Converted to attribute List
        json = "{\"id\": \"000000\",\"types\": \"[{\\\"name\\\":\\\"name1\\\",\\\"list\\\":[1,2]},{\\\"name\\\":\\\"name2\\\",\\\"list\\\":[3,4]}]\",\"keywordIds\": \"[12,13]\"}";
        System.out.println(json);
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));

        // 2.jsonArray It can also be changed to List
        json = "{\"id\": \"000000\",\"keywordIds\": [12,13],\"types\": [{\"name\":\"name1\",\"list\":[1,2]},{\"name\":\"name2\",\"list\":[3,4]}]}";
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));

        // 3. How to wrap lines 
        json = "{\n" +
                "\t\"id\": \"000000\",\n" +
                "\t\"keywordIds\": [12,13],\n" +
                "\t\"types\": [{\"name\":\"name1\",\"list\":[1,2]},{\"name\":\"name2\",\"list\":[3,4]}]\n" +
                "}";
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));

        // 4. Could you please List Inside Integer become String Well 
        json = "{\n" +
                "\t\"id\": \"000000\",\n" +
                "\t\"keywordIds\": [12,13],\n" +
                "\t\"types\": [{\"name\":\"name1\",\"list1\":[1,2]},{\"name\":\"name2\",\"list1\":[3,4]}]\n" +
                "}";
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));

        // 5. Could you please List Inside Integer become String
        json = "{\n" +
                "\t\"id\": \"000000\",\n" +
                "\t\"keywordIds1\": [12,13],\n" +
                "\t\"types\": [{\"name\":\"name1\",\"list1\":[1,2]},{\"name\":\"name2\",\"list1\":[3,4]}]\n" +
                "}";
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));

        // 6. Automatically put string Converted to attribute List,  also list Inside Integer Turn into String
        json = "{\"id\": \"000000\",\"types\": \"[{\\\"name\\\":\\\"name1\\\",\\\"list1\\\":[1,2]},{\\\"name\\\":\\\"name2\\\",\\\"list1\\\":[3,4]}]\",\"keywordIds1\": \"[12,13]\"}";
        System.out.println(json);
        requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType());
        Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0);
        System.out.println(gson.toJson(requestParam));
    }

    @Data
    public static class RequestParams {
        private String id;
        @JsonAdapter(CollectionStringTypeAdapterFactory.class)
        private List<TypeItem> types;
        @JsonAdapter(CollectionStringTypeAdapterFactory.class)
        private List<Integer> keywordIds;
        @JsonAdapter(CollectionStringTypeAdapterFactory.class)
        private List<String> keywordIds1;
    }
    @Data
    public static class TypeItem {
        private String name;
        private List<Integer> list;
        private List<String> list1;
    }
原网站

版权声明
本文为[ydfind]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/182/202207010625052701.html