You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:18:12