Gson错误?反序列化器的存在破坏了Gson中的序列化过程



在下面的例子中,我试图序列化我的自定义类Couple,它包含Point2D类型的字段。

我发现,序列化过程依赖于反序列化器的存在。

此外,如果存在反序列化器,则序列化过程工作错误。

描述剂如何影响逆向过程,如何破坏逆向过程?

未使用Point2DInstanceCreator

package tests;
import java.awt.geom.Point2D;
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

public class Try07_Point2D {
    static class Couple {
        Point2D p1, p2;
        public Couple() {
            p1 = new Point2D.Double();
            p2 = new Point2D.Double();
        }
        public Couple(double x1, double y1, double x2, double y2) {
            p1 = new Point2D.Double(x1, y1);
            p2 = new Point2D.Double(x2, y2);
        }
        void set(double x1, double y1, double x2, double y2) {
            p1.setLocation(x1, y1);
            p2.setLocation(x2, y2);
        }
        @Override
        public boolean equals(Object object) {
            if( object instanceof Couple) {
                Couple ano = (Couple) object;
                return 
                        (p1 == null && ano.p1 == null || p1 != null && p1.equals(ano.p1)) &&
                        (p2 == null && ano.p2 == null || p2 != null && p2.equals(ano.p2));
            }
            return false;
        }
    }
    static class Point2DInstanceCreator implements InstanceCreator<Point2D>{
        @Override
        public Point2D createInstance(Type type) {
            return new Point2D.Double();
        }
    }
    static class Point2DDeserializer implements JsonDeserializer<Point2D> {
        @Override
        public Point2D deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            Point2D.Double ans = new Point2D.Double();
            JsonObject obj = json.getAsJsonObject();
            ans.x = obj.get("x").getAsDouble();
            ans.y = obj.get("y").getAsDouble();
            return ans;
        }
    }
    public static void main(String[] args) {
        GsonBuilder gb;
        Gson gson0;
        gb = new GsonBuilder();
        gb = gb
         .enableComplexMapKeySerialization()
         .serializeNulls()
         .setPrettyPrinting()
         .setVersion(1.0)
    //     .registerTypeAdapter(Point2D.class, new Point2DInstanceCreator())
    //     .registerTypeAdapter(Point2D.class, new Point2DDeserializer())
         ;
        gson0 = gb.create();
        Couple value1;
        value1 = new Couple(12, 13, 14, 15);

        System.out.println("Version without deserializer:");
        System.out.println( gson0.toJson(value1) );
        gb = new GsonBuilder();
        gb = gb
         .enableComplexMapKeySerialization()
         .serializeNulls()
         .setPrettyPrinting()
         .setVersion(1.0)
//       .registerTypeAdapter(Point2D.class, new Point2DInstanceCreator())
         .registerTypeAdapter(Point2D.class, new Point2DDeserializer())
         ;
        gson0 = gb.create();

        System.out.println("Version with deserializer:");
        System.out.println( gson0.toJson(value1) );

    }
}
输出:

Version without deserializer:
{
  "p1": {
    "x": 12.0,
    "y": 13.0
  },
  "p2": {
    "x": 14.0,
    "y": 15.0
  }
}
Version with deserializer:
{
  "p1": {},
  "p2": {}
}

这看起来像是Gson中的一个bug。如果你注册了一个TypeAdaptor,看起来它同时被用于序列化和反序列化。

要解决这个问题,让你的Point2DDeserializer同时实现JsonDeserializer和JsonSerializer:

static class Point2DDeserializer implements JsonDeserializer<Point2D>, JsonSerializer<Point2D> {
    @Override
    public Point2D deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        Point2D.Double ans = new Point2D.Double();
        JsonObject obj = json.getAsJsonObject();
        ans.x = obj.get("x").getAsDouble();
        ans.y = obj.get("y").getAsDouble();
        return ans;
    }
    @Override
    public JsonElement serialize(final Point2D point2D, final Type type, final JsonSerializationContext jsonSerializationContext) {
        return new Gson().toJsonTree(point2D);
    }
}

最新更新