Gson无法反序列化含经纬度的数组问题求助
解决JSON数组反序列化到自定义类的问题
看起来你在这里踩了个常见的坑:你的JSON里geo是一个包含两个数值的数组(第一个是纬度,第二个是经度),但你现在把City类里的geo定义成了Geo[](Geo对象数组),这和JSON结构完全不匹配——因为JSON里并没有一系列Geo对象,只是两个纯数字而已。
下面给你几个可行的解决方案,按需选择:
方案1:直接用基础数组/List接收(最简单)
不需要额外的Geo类,直接把City里的geo字段改成double[]或者List<Double>,主流序列化框架(Jackson、Gson等)都能自动完成映射:
public static class City { private double[] geo; // 或者 private List<Double> geo; private String name; private String url; // Getter & Setter public double[] getGeo() { return geo; } public void setGeo(double[] geo) { this.geo = geo; } // 如果用List<Double>,替换成对应的Getter Setter // public List<Double> getGeo() { return geo; } // public void setGeo(List<Double> geo) { this.geo = geo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
之后你可以通过geo[0]获取纬度,geo[1]获取经度,完全不需要额外的反序列化逻辑。
方案2:自定义Geo类+反序列化器(更面向对象)
如果你还是想把经纬度封装成Geo对象,那就需要告诉序列化框架怎么把数组转成Geo实例。这里以常用的Jackson为例:
第一步:定义Geo类
先给Geo类加上lat和lon字段,以及对应的构造器、Getter和Setter:
public static class Geo { private double lat; private double lon; // Jackson默认需要无参构造器,或者用带参构造器配合注解 public Geo() {} public Geo(double lat, double lon) { this.lat = lat; this.lon = lon; } public double getLat() { return lat; } public void setLat(double lat) { this.lat = lat; } public double getLon() { return lon; } public void setLon(double lon) { this.lon = lon; } }
第二步:修改City类
把City里的geo字段改成单个Geo对象,而不是数组,并指定自定义反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public static class City { @JsonDeserialize(using = GeoDeserializer.class) private Geo geo; private String name; private String url; // 对应的Getter & Setter public Geo getGeo() { return geo; } public void setGeo(Geo geo) { this.geo = geo; } // 其他字段的Getter Setter不变 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
第三步:编写自定义反序列化器
这个类的作用就是把JSON数组转换成Geo对象:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; public class GeoDeserializer extends StdDeserializer<Geo> { public GeoDeserializer() { super(Geo.class); } @Override public Geo deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); // 取数组第一个元素作为纬度,第二个作为经度 double lat = node.get(0).asDouble(); double lon = node.get(1).asDouble(); return new Geo(lat, lon); } }
方案3:Gson用户的替代方案
如果你用的是Gson,那可以写一个TypeAdapter来实现数组到Geo对象的转换:
编写TypeAdapter
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; public class GeoTypeAdapter extends TypeAdapter<Geo> { @Override public void write(JsonWriter out, Geo geo) throws IOException { // 如果需要序列化Geo对象回数组,就写这个逻辑 out.beginArray(); out.value(geo.getLat()); out.value(geo.getLon()); out.endArray(); } @Override public Geo read(JsonReader in) throws IOException { in.beginArray(); double lat = in.nextDouble(); double lon = in.nextDouble(); in.endArray(); return new Geo(lat, lon); } }
注册TypeAdapter到Gson
import com.google.gson.Gson; import com.google.gson.GsonBuilder; Gson gson = new GsonBuilder() .registerTypeAdapter(Geo.class, new GeoTypeAdapter()) .create(); // 然后执行反序列化 City city = gson.fromJson(yourJsonString, City.class);
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

