2015-02-06 169 views
1

我对Gson和JSON都很新。 我的问题是当创建一个泛型类的列表并将其存储在包装obj中时,我无法反序列化回到子obj。Gson:从封装类中反序列化抽象子类的列表

这里是主代码

public static void main(String[] arg) { 
    block b = new block(); 

    List<Shape> shapes = new ArrayList<Shape>(); 

    Circle c = new Circle(); 
    c.setRadius(1); 
    c.setType("cir"); 
    Square s = new Square(); 
    s.setSide(4); 
    s.setType("sq"); 

    shapes.add(c); 
    shapes.add(s); 

    b.setShape(shapes); 

    String json = new Gson().toJson(b); 
    System.out.println(json); 

    Object obj = new Gson().fromJson(json, block.class); 
    block bobj = (block) obj; 

    List<Shape> li = bobj.getShape(); 
    Shape sh = (Shape)li.get(0); 

    System.out.println(sh.getClass().getCanonicalName()); 
    System.out.println(sh.toString()); 
} 

我得到这个作为输出

{"shape":[{"radius":1,"type":"cir"},{"side":4,"type":"sq"}]} 
    com.ups.pcs.test.TestTypeAdaptor.Shape 
    [email protected]

这里是我的代码的其余部分:

static class block implements Serializable { 
     List<Shape> shape = null; 

    public block() { 

    } 

    public List<Shape> getShape() { 
     return shape; 
    } 

    public void setShape(List<Shape> shape) { 
     this.shape = shape; 
    } 

    } 

    static class Shape implements Serializable{ 
    String type; 

    public Shape(){} 
    public void setType(String type) { 
     this.type = type; 
    } 

    public String getType() { 
     return type; 
    } 

    } 

    private static final class Circle extends Shape implements Serializable{ 
    int radius; 

    public Circle(){} 
    public int getRadius() { 
     return radius; 
    } 

    public void setRadius(int radius) { 
     this.radius = radius; 
    } 

    public String toString() { 
     return "t: " + type + "r: " + radius; 
    } 
    } 

    private static final class Square extends Shape implements Serializable{ 
    int side; 

    public Square(){} 
    public int getSide() { 
     return side; 
    } 

    public void setSide(int side) { 
     this.side = side; 
    } 

    public String toString() { 
     return "t: " + type + "s: " + side; 
    } 
    } 

我已经看到了一些帖子说起使用自定义typeAdaptor ortypeAdaptorFactory,我不知道如何使用。顺便说一句我正在使用Gson2.2.2版本

+0

同时修改Shape为抽象它无法成功运行。 '线程中的异常“main”java.lang.RuntimeException:无法调用public com.ups.pcs.test.TestTypeAdaptor $ Shape()with no args' – user3431327 2015-02-06 22:11:04

回答

2

这是我发现迄今为止的最佳答案... 请让我知道是否有人找到更好的解决方案,然后这个。 我还没有测试知道它运行的速度。

基本上为您的主对象创建自定义的反序列化器,并在查看每个对象时确定属性类。

public static class BlockDeserializer implements JsonDeserializer<Block> { 

    @Override 
    public Block deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     if (json == null) 
      return null; 
     else { 
      Block block = new Block(); 
      JsonObject jo = json.getAsJsonObject(); 
      JsonArray ja = jo.getAsJsonArray("shape"); 

      List<Shape> shapes = new ArrayList<Shape>(); 

      for(JsonElement je : ja) { 
       JsonObject jeo = je.getAsJsonObject(); 

       if(jeo.get("radius") != null) {    
        shapes.add(new Gson().fromJson(jeo , Circle.class));      
       } else { 
        shapes.add(new Gson().fromJson(jeo , Square.class));   
       } 
      } 

      block.shape = shapes; 

      return block; 
     } 
    } 
}