Commit 9e052af6 authored by Volker Krause's avatar Volker Krause
Browse files

Factor out the GBFS top-level data element parsing

This now also handles the case of feeds missing the top-level data element
and putting the content directly into the document. That seems to be a
common mistake in older feeds, possibly caused by ambiguities in the
specification at the time.
parent 153dbf50
......@@ -105,11 +105,11 @@ static void appendResults(const GBFSService &service, const LocationRequest &req
RentalVehicleNetwork network;
const auto sysInfoDoc = store.loadData(GBFS::SystemInformation);
const auto sysInfo = sysInfoDoc.object().value(QLatin1String("data")).toObject();
const auto sysInfo = GBFSReader::dataObject(sysInfoDoc);
network.setName(sysInfo.value(QLatin1String("name")).toString());
const auto stationsDoc = store.loadData(GBFS::StationInformation);
const auto stations = stationsDoc.object().value(QLatin1String("data")).toObject().value(QLatin1String("stations")).toArray();
const auto stations = GBFSReader::dataValue(stationsDoc, QLatin1String("stations")).toArray();
std::vector<QString> selectedStationIds;
for (const auto &stationV : stations) {
......@@ -139,7 +139,7 @@ static void appendResults(const GBFSService &service, const LocationRequest &req
}
const auto statusDoc = store.loadData(GBFS::StationStatus);
const auto status = statusDoc.object().value(QLatin1String("data")).toObject().value(QLatin1String("stations")).toArray();
const auto status = GBFSReader::dataValue(statusDoc, QLatin1String("stations")).toArray();
for (const auto &statV : status) {
const auto stat = statV.toObject();
const auto id = stationIdToString(stat.value(QLatin1String("station_id")));
......@@ -155,7 +155,7 @@ static void appendResults(const GBFSService &service, const LocationRequest &req
}
const auto floatingDoc = store.loadData(GBFS::FreeBikeStatus);
const auto floating = floatingDoc.object().value(QLatin1String("data")).toObject().value(QLatin1String("bikes")).toArray();
const auto floating = GBFSReader::dataValue(floatingDoc, QLatin1String("bikes")).toArray();
for (const auto &bikeV : floating) {
const auto bike = bikeV.toObject();
if (bike.value(QLatin1String("is_reserved")).toBool() || bike.value(QLatin1String("is_disabled")).toBool()) {
......
......@@ -263,8 +263,7 @@ void GBFSJob::parseData(const QJsonDocument &doc, GBFS::FileType type)
void GBFSJob::parseSystemInformation(const QJsonDocument &doc)
{
const auto data = doc.object().value(QLatin1String("data")).toObject();
const auto systemId = data.value(QLatin1String("system_id")).toString();
const auto systemId = GBFSReader::dataValue(doc, QLatin1String("system_id")).toString();
if (systemId.isEmpty()) {
m_error = DataError;
m_errorMsg = QStringLiteral("unable to determine system_id!");
......@@ -287,14 +286,14 @@ void GBFSJob::parseSystemInformation(const QJsonDocument &doc)
void GBFSJob::parseStationInformation(const QJsonDocument &doc)
{
const auto stations = doc.object().value(QLatin1String("data")).toObject().value(QLatin1String("stations")).toArray();
const auto stations = GBFSReader::dataValue(doc, QLatin1String("stations")).toArray();
collectCoordinates(stations);
qDebug() << stations.size() << "stations/docks";
}
void GBFSJob::parseFreeBikeStatus(const QJsonDocument &doc)
{
const auto bikes = doc.object().value(QLatin1String("data")).toObject().value(QLatin1String("bikes")).toArray();
const auto bikes = GBFSReader::dataValue(doc, QLatin1String("bikes")).toArray();
collectCoordinates(bikes);
qDebug() << bikes.size() << "free floating vehicles";
}
......@@ -364,7 +363,7 @@ void GBFSJob::collectCoordinates(const QJsonArray &array)
void GBFSJob::parseVersionData(const QJsonDocument &doc)
{
m_versionDoc = doc;
const auto versions = doc.object().value(QLatin1String("data")).toObject().value(QLatin1String("versions")).toArray();
const auto versions = GBFSReader::dataValue(doc, QLatin1String("versions")).toArray();
QJsonObject bestVersion;
for (const auto &verVal : versions) {
const auto version = verVal.toObject();
......@@ -391,8 +390,7 @@ void GBFSJob::parseVersionData(const QJsonDocument &doc)
void GBFSJob::parseGeofencingZones(const QJsonDocument &doc)
{
const auto features = doc.object().value(QLatin1String("data")).toObject()
.value(QLatin1String("geofencing_zones")).toObject()
const auto features = GBFSReader::dataValue(doc, QLatin1String("geofencing_zones")).toObject()
.value(QLatin1String("features")).toArray();
for (const auto &featureVal : features) {
const auto geo = featureVal.toObject().value(QLatin1String("geometry")).toObject();
......
......@@ -6,6 +6,7 @@
#include "gbfsreader.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <cmath>
......@@ -34,3 +35,18 @@ double GBFSReader::readLongitude(const QJsonObject &obj)
{
return readDouble(obj.value(QLatin1String("lon")));
}
QJsonObject GBFSReader::dataObject(const QJsonDocument &doc)
{
const auto obj = doc.object();
const auto it = obj.find(QLatin1String("data"));
if (it == obj.end() || !(*it).isObject()) {
return obj;
}
return (*it).toObject();
}
QJsonValue GBFSReader::dataValue(const QJsonDocument &doc, QLatin1String name)
{
return dataObject(doc).value(name);
}
......@@ -7,7 +7,10 @@
#ifndef KPUBLICTRANSPORT_GBFSREADER_H
#define KPUBLICTRANSPORT_GBFSREADER_H
class QJsonDocument;
class QJsonObject;
class QJsonValue;
class QLatin1String;
namespace KPublicTransport {
......@@ -17,6 +20,13 @@ namespace GBFSReader
/** Reads and sanity-checks geographic coordinates. */
double readLatitude(const QJsonObject &obj);
double readLongitude(const QJsonObject &obj);
/** Returns the top-level data object.
* Also handles broken feeds missing the data object and having things
* on the top level directly.
*/
QJsonObject dataObject(const QJsonDocument &doc);
QJsonValue dataValue(const QJsonDocument &doc, QLatin1String name);
}
}
......
......@@ -7,6 +7,7 @@
#include "gbfsvehicletypes.h"
#include "gbfs.h"
#include "gbfsreader.h"
#include "gbfsservice.h"
#include "gbfsstore.h"
......@@ -75,7 +76,7 @@ GBFSVehicleTypes::GBFSVehicleTypes(const GBFSService &feed)
{
GBFSStore store(feed.systemId);
const auto doc = store.loadData(GBFS::VehicleTypes);
const auto types = doc.object().value(QLatin1String("data")).toObject().value(QLatin1String("vehicle_types")).toArray();
const auto types = GBFSReader::dataValue(doc, QLatin1String("vehicle_types")).toArray();
m_vehicleTypes.reserve(types.size());
for (const auto &typeVal : types) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment