How could I read JSON data from here: http://data.foli.fi/siri/vm using Jackson for example, so it returns the data filtered like this:
[{
"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
}]
I've tried to use a bean like this but it doesn't seem to work..
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 + " }]" + "\"";
}
}
I've tried using a reader, but the result is always null.
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 }]
For filtering you could just use Jackson ObjectMapper and JsonNode to manually filter and map out the fields from the json response to list of FilteredResult objects.
package com.example;
import java.util.ArrayList;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.JsonLibrary;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import com.example.utilities.files.FileReadUtility;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class FoliFilter extends CamelTestSupport {
@Test
public void testRunFilter() {
String json = FileReadUtility.readResourceAsString("responses/foli.json");
template.sendBody("direct:filterJson", json);
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:filterJson")
.routeId("filterJson")
.process(ex -> {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode tree = objectMapper.readTree(ex.getMessage().getBody(String.class));
JsonNode vehicles = tree.path("result").path("vehicles");
if (!vehicles.isMissingNode()) {
ArrayList<FilteredResult> filtered = new ArrayList<>();
for (JsonNode jsonNode : vehicles) {
//Many nodes seem to be missing most of the data, so using this to skip those entries.
if(!jsonNode.has("originname")){
continue;
}
FilteredResult newFilteredResult = new FilteredResult();
newFilteredResult.setId(jsonNode.path("originname").asText("Missing"));
newFilteredResult.setName(jsonNode.path("publishedlinename").asText("Missing"));
String description = jsonNode.path("publishedlinename").asText("Missing")
+ ": " + jsonNode.path("destinationname").asText("Missing")
+ " -> " + jsonNode.path("originname").asText("Missing");
newFilteredResult.setDescription(description);
newFilteredResult.setLongitude(jsonNode.path("longitude").asDouble(0.0));
newFilteredResult.setLatitude(jsonNode.path("latitude").asDouble(0.0));
filtered.add(newFilteredResult);
}
ex.getMessage().setBody(filtered);
}
})
.marshal().json(JsonLibrary.Jackson)
.log("${body}");
}
};
}
}
class FilteredResult {
private String id;
private String name;
private String description;
private double latitude;
private double longitude;
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;
}
}
There are probably ways to do this more elegantly in Camel and would also be interested to see how. I've also tried using JsonPath for stuff like this with mixed results.
The FileReadUtility is just a utility class for loading text-files as strings from resources folder.
package com.example.utilities.files;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
public final class FileReadUtility {
private FileReadUtility(){}
public static String readResourceAsString(String pathInResources) throws IOException{
ClassLoader classLoader = FileReadUtility.class.getClassLoader();
File file = new File(classLoader.getResource(pathInResources).getFile());
return FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
}
public static byte[] readResourceAsBytes(String pathInResources) throws IOException{
ClassLoader classLoader = FileReadUtility.class.getClassLoader();
File file = new File(classLoader.getResource(pathInResources).getFile());
return FileUtils.readFileToByteArray(file);
}
}
Maven depedency for Apache Commons IO
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>