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

使用Jackson ObjectMapper将JSON映射至Google DirectionsResult时,EncodedPolyline的points属性无法赋值的解决方法

解决Jackson映射Google DirectionsResult时overview_polyline.points为null的问题

这个问题的核心在于Google Maps Java客户端库中的EncodedPolyline类的设计限制:它的points字段是私有且没有公共setter方法,同时无参构造器直接将points初始化为null。Jackson默认会通过无参构造器创建对象,然后尝试通过setter或直接访问字段来赋值,但由于上述限制,无法将JSON中的points值注入进去。

下面提供几种可行的解决方案,按推荐程度排序:

方案一:自定义EncodedPolyline反序列化器(推荐)

我们可以为EncodedPolyline编写一个自定义的Jackson反序列化器,通过反射绕过私有字段的访问限制,直接设置points值:

1. 实现反序列化器

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 com.google.maps.model.EncodedPolyline;
import java.io.IOException;
import java.lang.reflect.Field;

public class EncodedPolylineDeserializer extends StdDeserializer<EncodedPolyline> {

    public EncodedPolylineDeserializer() {
        super(EncodedPolyline.class);
    }

    @Override
    public EncodedPolyline deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 读取JSON节点中的points值
        JsonNode node = p.getCodec().readTree(p);
        String points = node.get("points").asText();

        // 创建EncodedPolyline实例并通过反射设置points字段
        EncodedPolyline polyline = new EncodedPolyline();
        try {
            Field pointsField = EncodedPolyline.class.getDeclaredField("points");
            pointsField.setAccessible(true); // 允许访问私有字段
            pointsField.set(polyline, points);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new IOException("Failed to inject points into EncodedPolyline", e);
        }

        return polyline;
    }
}

2. 注册反序列化器到ObjectMapper

在你的映射代码中,把这个反序列化器注册到ObjectMapper:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

// 注册自定义反序列化器
objectMapper.registerModule(new SimpleModule()
        .addDeserializer(EncodedPolyline.class, new EncodedPolylineDeserializer()));

// 现在再进行映射
DirectionsResult result = objectMapper.readValue(json, DirectionsResult.class);

方案二:使用适配POJO中转

如果不想编写反序列化器,可以先将JSON映射到自己定义的适配POJO,再手动转换为Google的DirectionsResult对象:

1. 定义适配POJO

import com.google.maps.model.Bounds;
import com.google.maps.model.Leg;
import com.google.maps.model.GeocodedWaypoint;

import java.util.List;

public class MyDirectionsResult {
    private List<GeocodedWaypoint> geocodedWaypoints;
    private List<MyRoute> routes;

    // Getters and Setters

    public static class MyRoute {
        private Bounds bounds;
        private List<Leg> legs;
        private MyEncodedPolyline overviewPolyline;
        private List<String> warnings;
        private List<Integer> waypointOrder;

        // Getters and Setters
    }

    public static class MyEncodedPolyline {
        private String points;

        // Getters and Setters
    }
}

2. 转换为Google的DirectionsResult

// 先映射到自定义POJO
MyDirectionsResult myResult = objectMapper.readValue(json, MyDirectionsResult.class);

// 手动转换为Google的DirectionsResult
DirectionsResult result = new DirectionsResult();
result.geocodedWaypoints = myResult.getGeocodedWaypoints().toArray(new GeocodedWaypoint[0]);

List<com.google.maps.model.Route> googleRoutes = new ArrayList<>();
for (MyRoute myRoute : myResult.getRoutes()) {
    com.google.maps.model.Route googleRoute = new com.google.maps.model.Route();
    googleRoute.bounds = myRoute.getBounds();
    googleRoute.legs = myRoute.getLegs().toArray(new Leg[0]);
    googleRoute.warnings = myRoute.getWarnings().toArray(new String[0]);
    googleRoute.waypointOrder = myRoute.getWaypointOrder().stream().mapToInt(Integer::intValue).toArray();

    // 处理overviewPolyline
    EncodedPolyline polyline = new EncodedPolyline();
    try {
        Field pointsField = EncodedPolyline.class.getDeclaredField("points");
        pointsField.setAccessible(true);
        pointsField.set(polyline, myRoute.getOverviewPolyline().getPoints());
        googleRoute.overviewPolyline = polyline;
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

    googleRoutes.add(googleRoute);
}
result.routes = googleRoutes.toArray(new com.google.maps.model.Route[0]);

方案三:直接反射修复(应急用)

如果只是临时解决,可以在映射完成后,通过反射遍历routes中的overviewPolyline,手动设置points值:

DirectionsResult result = objectMapper.readValue(json, DirectionsResult.class);

// 遍历所有route,修复overviewPolyline的points
for (com.google.maps.model.Route route : result.routes) {
    if (route.overviewPolyline != null) {
        // 从JSON中重新提取points(或者你可以在映射时先把JSON存下来)
        JsonNode rootNode = objectMapper.readTree(json);
        String points = rootNode.get("routes").get(0).get("overview_polyline").get("points").asText();

        try {
            Field pointsField = EncodedPolyline.class.getDeclaredField("points");
            pointsField.setAccessible(true);
            pointsField.set(route.overviewPolyline, points);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

这个方案比较繁琐,不推荐在生产环境使用,但应急时可以快速生效。


内容的提问来源于stack exchange,提问作者phạm Tiến

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:44:05