读书后,亲子铸造

发布于 2025-02-11 08:21:44 字数 1079 浏览 2 评论 0原文

我有一个父母,让我们称其为具有名称和颜色的自行车。

public class Bike(){
    String name;
    String color;

}

我有2个孩子

public class TrickBike extends Bike(){
    ...
    ...
    public doTrick(){

    }
}

public class FailBike extends Bike(){
   ...
   ...
   public doFail(){

   }
}

,所有这些都有适当的约束超级呼叫和所有内容。我现在有一个装有自行车的车库。

public class Garage(){
     List<Bike> bikes;

}

我添加了一堆自行车,所有三种类型(自行车,trickbike,failbike)。现在,我将其写入一个JSON字符串,然后将其写入GSON文件。然后,我稍后将带有GSON的JSON文件的车库,我想尝试在Trickbike上尝试dotrick()。由于JSON转换,我无法施放自行车现在Trickbike(这是来自试用和错误,并且在Java中获得异常)。那么如何恢复该儿童功能?

有安全的方法吗?不安全的方式?如果我尝试dotrick()failbike上会发生什么?我可以让自行车尝试和dotrick()吗?

谢谢。

编辑:我想修复此后的GSON阅读。另外,我不阅读类型trickbikebikefailbike in。具有列表&lt; bike&gt;,这样就不起作用。

解决方案:我迁移到使用杰克逊,并能够使用注释和带有类型标签的@jsontypeinfo成功实现此行为。所以杰克逊&gt; GSON多态性。

I have a parent, lets call it Bike that has a name and a color.

public class Bike(){
    String name;
    String color;

}

I have 2 children

public class TrickBike extends Bike(){
    ...
    ...
    public doTrick(){

    }
}

public class FailBike extends Bike(){
   ...
   ...
   public doFail(){

   }
}

These all have appropriate construtor super calls and everything. I now have a garage that holds bikes.

public class Garage(){
     List<Bike> bikes;

}

I add a bunch of bikes, all 3 types(Bike, TrickBike,FailBike). Now, I write this to a JSON String and dump to file with GSON. I then at a later time get the Garage from the JSON file with GSON and I want to try to doTrick() on a TrickBike. I can't cast Bike to TrickBike now because of the Json conversion (this is from trial and error and getting exception in java). So how do I restore this child functionality?

Is there a safe way of doing this? An unsafe way? If I try doTrick() on a FailBike what happens? Can I get the Bike to try and doTrick()?

Thanks.

EDIT: I would like to fix this post-GSON read in. @Chaosfire mentioned copying some GSON source code from the linked question but I would not like to do this for a variety of reasons. Also, I am not reading types TrickBike and Bike or FailBike in. I am reading in the Garage which merely has a List<Bike> so that wouldn't work.

SOLUTION: I migrated over to using jackson and was able to successfully implement this behavior using annotations and @JsonTypeInfo with type labels. So Jackson > Gson for polymorphism.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瑕疵 2025-02-18 08:21:44

据我所知,您需要自定义序列化/避难所化。我认为GSON没有功能将类型信息添加到JSON。

public class BikeTypeAdapter implements JsonSerializer<Bike>, JsonDeserializer<Bike> {

  private final Gson gson = new Gson();
  private final String typeField = "type";

  @Override
  public Bike deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    String type = ((JsonObject) json).get(this.typeField).getAsString();
    Bike bike;
    try {
      //instantiate with default constructor
      bike = (Bike) Class.forName(type).getConstructor().newInstance();
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }
    bike.setColor(((JsonObject) json).get("color").getAsString());
    bike.setName(((JsonObject) json).get("name").getAsString());
    return bike;
  }

  @Override
  public JsonElement serialize(Bike src, Type typeOfSrc, JsonSerializationContext context) {
    JsonObject object = this.gson.toJsonTree(src).getAsJsonObject();
    object.addProperty(this.typeField, src.getClass().getCanonicalName());
    return object;
  }
}

有些简化的示例,该示例在序列化过程中添加了具有规范类名称的属性,并在避难化期间使用它来创建正确的类实例。

示例用法:

public static void main(String[] args) {
  Garage garage = new Garage();
  garage.bikes.add(new Bike("normal", "red"));
  garage.bikes.add(new TrickBike("trick", "blue"));
  garage.bikes.add(new FailBike("fail", "green"));
  Gson gson = new GsonBuilder()
          .registerTypeAdapter(Bike.class, new BikeTypeAdapter())
          .create();
  String json = gson.toJson(garage);
  System.out.println(json);
  Garage garage1 = gson.fromJson(json, Garage.class);
  System.out.println(garage1);
}

In my knowledge you would need custom serialization/deserialization. I don't think Gson has functionality add type information to json.

public class BikeTypeAdapter implements JsonSerializer<Bike>, JsonDeserializer<Bike> {

  private final Gson gson = new Gson();
  private final String typeField = "type";

  @Override
  public Bike deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    String type = ((JsonObject) json).get(this.typeField).getAsString();
    Bike bike;
    try {
      //instantiate with default constructor
      bike = (Bike) Class.forName(type).getConstructor().newInstance();
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }
    bike.setColor(((JsonObject) json).get("color").getAsString());
    bike.setName(((JsonObject) json).get("name").getAsString());
    return bike;
  }

  @Override
  public JsonElement serialize(Bike src, Type typeOfSrc, JsonSerializationContext context) {
    JsonObject object = this.gson.toJsonTree(src).getAsJsonObject();
    object.addProperty(this.typeField, src.getClass().getCanonicalName());
    return object;
  }
}

Somewhat simplified example, which adds property with canonical class name during serialization, and uses it during deserialization to create instance of correct class.

Example usage:

public static void main(String[] args) {
  Garage garage = new Garage();
  garage.bikes.add(new Bike("normal", "red"));
  garage.bikes.add(new TrickBike("trick", "blue"));
  garage.bikes.add(new FailBike("fail", "green"));
  Gson gson = new GsonBuilder()
          .registerTypeAdapter(Bike.class, new BikeTypeAdapter())
          .create();
  String json = gson.toJson(garage);
  System.out.println(json);
  Garage garage1 = gson.fromJson(json, Garage.class);
  System.out.println(garage1);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文