Java对象与可变维数组

4

我正在尝试使用Gson解析GeoJSON,我有一个看起来像这样(简化)的JSON:

{"type": "FeatureCollection",
 "features": [
{ "type": "Feature", "name": "Afghanistan", "geometry": 
    { "type": "Polygon", "coordinates": 
        <<a 3-dimensional double array (double[][][] in Java)>>
    } 
},
{ "type": "Feature", "name": "Indonesia", "geometry":
    { "type": "MultiPolygon", "coordinates":
        <<a 4-dimensional double array (double[][][][] in Java)>>
    }
},
//etc...
 ]
}

我需要一个Java类,可以与Gson对象相关联以便使用,但我在处理一组具有不同变量“坐标”的相似对象时遇到了困难。 我有以下等效代码:

class FeatureCollection{
    String type;
    Feature[] features;
}
class Feature{
    String type,name;
    Shape geometry;
}
class Shape{
    String type;
    ??? coordinates;
}
  • 当我尝试使用 double[][][] 而不是 ??? 时,我会得到一个 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a double but was BEGIN_ARRAY at line 6 column 146 的错误。
  • 当我尝试将 Shape 变成抽象类并使用 MultiPolygonPolygon 的子类时,Gson 尝试实例化一个 Shape 并出现错误。

我可以使用泛型或其他巧妙的方法来解决这个问题吗?

1个回答

3

由于 coordinates 变量没有定义一组数组维度,您需要自己编写一个自定义 JsonDeserializer。我建议使用一个接口来描述形状,并为其编写一个反序列化器,像这样:

public interface Shape {

    ShapeType getType();

    enum ShapeType { Polygon, MultiPolygon }
}

然后是每种类型的实现。 ShapeType.Polygon:

public class PolygonShape implements Shape {

    private final ShapeType type = ShapeType.Polygon;
    private double[][][] coordinates;

    public ShapeType getType() {
        return type;
    }

    public double[][][] getCoordinates() {
        return coordinates;
    }

    public void setCoordinates(double[][][] coordinates) {
        this.coordinates = coordinates;
    }
}

对于 ShapeType.MultiPolygon

public class MultiPolygonShape implements Shape {

    private final ShapeType type = ShapeType.MultiPolygon;
    private double[][][][] coordinates;

    public ShapeType getType() {
        return type;
    }

    public double[][][][] getCoordinates() {
        return coordinates;
    }

    public void setCoordinates(double[][][][] coordinates) {
        this.coordinates = coordinates;
    }
}

最后,您的反序列化程序将依赖于每个实现中的type

public class ShapeDeserializer implements JsonDeserializer<Shape> {

    @Override
    public Shape deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        ShapeType type = context.deserialize(jsonObject.get("type"), ShapeType.class);
        switch (type) {
            case Polygon:
                return context.deserialize(json, PolygonShape.class);
            case MultiPolygon:
                return context.deserialize(json, MultiPolygonShape.class);
            default:
                throw new JsonParseException("Unrecognized shape type: " + type);
        }
    }
}

使用这种方法,您还可以根据形状类型创建其他实现,并将它们添加到switch中以支持它们。例如,要支持新的Line类型:
case Line:
    return context.deserialize(json, LineShape.class);

别忘了使用GsonBuilder.registerTypeAdapter方法进行注册:

GsonBuilder builder;
// ...
builder.registerTypeAdapter(Shape.class, new ShapeDeserializer());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接