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

如何用Jackson读取指定URL的JSON数据并过滤为目标格式?

解决Jackson解析公交JSON数据为空的问题

需求说明

需要从http://data.foli.fi/siri/vm读取JSON数据,并转换为如下格式的数组:

[{
    "latitude": 60.4827,
    "name": "14",
    "description": "14: Saramäki -> Erikvalla",
    "id": "550018",
    "longitude": 22.31275
}, {
    "latitude": 60.45902,
    "name": "20",
    "description": "20: Puutori -> Muhkuri",
    "id": "110416",
    "longitude": 22.26783
}]

当前问题

编写的ItemsBean解析后所有字段为空(或默认值),日志输出:

2022-08-17 11:43:34,714 INFO  [get-map-data] (vert.x-worker-thread-1) null
2022-08-17 11:43:34,715 INFO  [get-map-data] (vert.x-worker-thread-1) Data for the map: http://data.foli.fi/siri/vm
2022-08-17 11:43:34,716 INFO  [get-map-data] (vert.x-worker-thread-1) [{ latitude: 0.0, name: null, description: null: null -> null, id: null, longitude: 0.0 }]

原ItemsBean代码:

public class ItemsBean{

        private double latitude;
        @JsonProperty("name")
        private String publishedlinename;
        @JsonProperty("id")
        private String originname;
        private String destinationname;
        private String vehicleref;
        private double longitude;

        @JsonIgnore
        public String sys;
        public int servertime;
        public int responsetimestamp;
        public String producerref;
        public String responsemessageidentifier;
        public boolean status;
        public boolean moredata;
        public int recordedattime;
        public int validuntiltime;
        public int linkdistance;
        public double percentage;
        public String lineref;
        public String directionref;
        public String operatorref;
        public String originref;
        public String destinationref;
        public int originaimeddeparturetime;
        public int destinationaimedarrivaltime;
        public boolean monitored;
        public boolean incongestion;
        public boolean inpanic;
        public String delay;
        public int delaysecs;
        public String blockref;
        public String next_stoppointref;
        public int next_visitnumber;
        public String next_stoppointname;
        public boolean vehicleatstop;
        public String next_destinationdisplay;
        public int next_aimedarrivaltime;
        public int next_expectedarrivaltime;
        public int next_aimeddeparturetime;
        public String destinationname_sv;
        public String next_stoppointname_sv;
        public String __tripref;
        public String __routeref;
        public String __directionid;
        public String originname_sv;
        public String next_destinationdisplay_sv;

        public ItemsBean(){}

        public ItemsBean(double latitude, String publishedlinename, String originname, String destinationname, String vehicleref, double longitude) {

            this.latitude = latitude;
            this.publishedlinename = publishedlinename;
            this.originname = originname;
            this.destinationname = destinationname;
            this.vehicleref = vehicleref;
            this.longitude = longitude;
        }

        public double getLatitude() {
            return latitude;
        }
        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }
        public String getPublishedlinename() {
            return publishedlinename;
        }
        public void setPublishedlinename(String publishedlinename) {
            this.publishedlinename = publishedlinename;
        }
        public String getOriginname() {
            return originname;
        }
        public void setOriginname(String originname) {
            this.originname = originname;
        }
        public String getNext_destinationdisplay() {
            return destinationname;
        }
        public void setDestinationname(String destinationname) {
            this.destinationname = destinationname;
        }
        public String getVehicleref() {
            return vehicleref;
        }
        public void setVehicleref(String vehicleref) {
            this.vehicleref = vehicleref;
        }
        public double getLongitude() {
            return longitude;
        }
        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }

        @Override
        public String toString() {
            return "\"" + "[{ " + "latitude: " + latitude + ", " +
                        "name: " + publishedlinename + ", " +
                        "description: " + publishedlinename + ": " + originname + " -> " + destinationname + ", " +
                        "id: " + vehicleref + ", " +
                        "longitude: " + longitude + " }]" + "\"";
        }
    }

问题分析

  1. JSON结构匹配错误:目标URL返回的JSON是多层嵌套结构,车辆数据实际位于Siri.ServiceDelivery.VehicleMonitoringDelivery[0].VehicleActivity路径下,直接解析成ItemsBean数组无法定位到目标字段。
  2. JsonProperty注解逻辑颠倒:原代码将Java属性映射为输出字段名,而解析时需要将JSON中的原始字段名映射到Java属性,方向完全错误。
  3. 字段映射完全错误:比如目标id对应JSON中的VehicleRef,name对应PublishedLineName,原代码的属性与JSON字段完全不匹配。
  4. 冗余字段未忽略:大量不需要的公共字段未添加@JsonIgnore,干扰Jackson的字段匹配逻辑。

解决方案

步骤1:修正实体类结构

创建匹配原始JSON嵌套结构的类,仅保留需要的字段,多余字段全部忽略:

顶级响应类:SiriResponse.java

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
public class SiriResponse {
    @JsonProperty("Siri")
    private Siri siri;

    public Siri getSiri() {
        return siri;
    }

    public void setSiri(Siri siri) {
        this.siri = siri;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Siri {
        @JsonProperty("ServiceDelivery")
        private ServiceDelivery serviceDelivery;

        public ServiceDelivery getServiceDelivery() {
            return serviceDelivery;
        }

        public void setServiceDelivery(ServiceDelivery serviceDelivery) {
            this.serviceDelivery = serviceDelivery;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class ServiceDelivery {
        @JsonProperty("VehicleMonitoringDelivery")
        private List<VehicleMonitoringDelivery> vehicleMonitoringDeliveries;

        public List<VehicleMonitoringDelivery> getVehicleMonitoringDeliveries() {
            return vehicleMonitoringDeliveries;
        }

        public void setVehicleMonitoringDeliveries(List<VehicleMonitoringDelivery> vehicleMonitoringDeliveries) {
            this.vehicleMonitoringDeliveries = vehicleMonitoringDeliveries;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class VehicleMonitoringDelivery {
        @JsonProperty("VehicleActivity")
        private List<VehicleActivity> vehicleActivities;

        public List<VehicleActivity> getVehicleActivities() {
            return vehicleActivities;
        }

        public void setVehicleActivities(List<VehicleActivity> vehicleActivities) {
            this.vehicleActivities = vehicleActivities;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class VehicleActivity {
        @JsonProperty("MonitoredVehicleJourney")
        private MonitoredVehicleJourney monitoredVehicleJourney;
        @JsonProperty("VehicleLocation")
        private VehicleLocation vehicleLocation;

        public MonitoredVehicleJourney getMonitoredVehicleJourney() {
            return monitoredVehicleJourney;
        }

        public void setMonitoredVehicleJourney(MonitoredVehicleJourney monitoredVehicleJourney) {
            this.monitoredVehicleJourney = monitoredVehicleJourney;
        }

        public VehicleLocation getVehicleLocation() {
            return vehicleLocation;
        }

        public void setVehicleLocation(VehicleLocation vehicleLocation) {
            this.vehicleLocation = vehicleLocation;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class MonitoredVehicleJourney {
        @JsonProperty("VehicleRef")
        private String vehicleRef;
        @JsonProperty("PublishedLineName")
        private String publishedLineName;
        @JsonProperty("OriginName")
        private String originName;
        @JsonProperty("DestinationName")
        private String destinationName;

        public String getVehicleRef() {
            return vehicleRef;
        }

        public void setVehicleRef(String vehicleRef) {
            this.vehicleRef = vehicleRef;
        }

        public String getPublishedLineName() {
            return publishedLineName;
        }

        public void setPublishedLineName(String publishedLineName) {
            this.publishedLineName = publishedLineName;
        }

        public String getOriginName() {
            return originName;
        }

        public void setOriginName(String originName) {
            this.originName = originName;
        }

        public String getDestinationName() {
            return destinationName;
        }

        public void setDestinationName(String destinationName) {
            this.destinationName = destinationName;
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class VehicleLocation {
        @JsonProperty("Latitude")
        private double latitude;
        @JsonProperty("Longitude")
        private double longitude;

        public double getLatitude() {
            return latitude;
        }

        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }

        public double getLongitude() {
            return longitude;
        }

        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }
    }
}

目标输出类:MapVehicle.java

public class MapVehicle {
    private double latitude;
    private String name;
    private String description;
    private String id;
    private double longitude;

    public MapVehicle(double latitude, String name, String description, String id, double longitude) {
        this.latitude = latitude;
        this.name = name;
        this.description = description;
        this.id = id;
        this.longitude = longitude;
    }

    // Getters and Setters
    public double getLatitude() { return latitude; }
    public void setLatitude(double latitude) { this.latitude = latitude; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public double getLongitude() { return longitude; }
    public void setLongitude(double longitude) { this.longitude = longitude; }
}

步骤2:解析并转换数据

编写代码读取URL数据,解析后转换成目标格式:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.stream.Collectors;

public class VehicleDataParser {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws IOException {
        // 读取并解析原始JSON
        URL url = new URL("http://data.foli.fi/siri/vm");
        SiriResponse response = objectMapper.readValue(url, SiriResponse.class);

        // 提取车辆数据并转换成目标格式
        List<MapVehicle> mapVehicles = response.getSiri().getServiceDelivery().getVehicleMonitoringDeliveries().get(0)
                .getVehicleActivities().stream()
                .map(activity -> {
                    SiriResponse.MonitoredVehicleJourney journey = activity.getMonitoredVehicleJourney();
                    SiriResponse.VehicleLocation location = activity.getVehicleLocation();
                    String description = String.format("%s: %s -> %s",
                            journey.getPublishedLineName(),
                            journey.getOriginName(),
                            journey.getDestinationName());
                    return new MapVehicle(
                            location.getLatitude(),
                            journey.getPublishedLineName(),
                            description,
                            journey.getVehicleRef(),
                            location.getLongitude()
                    );
                })
                .collect(Collectors.toList());

        // 输出目标格式的JSON
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapVehicles));
    }
}

关键修正点

  1. 嵌套结构匹配:通过多层静态类精准匹配原始JSON的嵌套路径,确保Jackson能正确定位到车辆数据。
  2. 字段映射准确:@JsonProperty注解完全对应原始JSON中的字段名,保证解析时字段能正确赋值。
  3. 忽略未知字段:所有类添加@JsonIgnoreProperties(ignoreUnknown = true),避免多余字段干扰解析逻辑。
  4. 分离解析与转换:先解析原始数据,再通过Stream API转换成目标格式,逻辑清晰易维护。

验证结果

运行代码后,将输出符合需求的JSON数组,每个对象的latitude、name、description、id、longitude字段均会被正确填充。

内容的提问来源于stack exchange,提问作者MikaelL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 22:24:23