[GIS] OpenLayers3 and GeoJSON data with null features

geojsonjavascriptopenlayers

I am new to OpenLayers and I'm trying to label features on a map using a GeoJSON data. Here is my code:

var layer = new ol.layer.VectorTile({
    source: new ol.source.VectorTile({
        format: new ol.format.GeoJSON(),
        tileGrid: ol.tilegrid.createXYZ(),
        url: "http://abcd.com/cities/{z}/{x}/{y}.geojson"
    })
})

Sometimes I get "features": null in the GeoJSON data:

{ "type": "FeatureCollection", "features": null }

and features parsing fails with error Uncaught TypeError: Cannot read property 'length' of null. Is it possible to replace null by [] before parsing features?

UPDATE. I found a solution, but got a new issue: I can't add features to the source. Here is my code (I'm using OpenLayers 3.9.0):

var format = new ol.format.GeoJSON();
var source = new ol.source.TileVector({
    tileGrid: ol.tilegrid.createXYZ(),
    tileLoadFunction: function (url) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onreadystatechange = function () {
            if (XMLHttpRequest.DONE === xhr.readyState && 200 === xhr.status) {
                var json = xhr.responseText.replace("null", "[]");
                var features = format.readFeatures(json, {
                    featureProjection: "EPSG:3857"
                });
                features.forEach(function (f) {
                    console.log(f.getGeometry().getCoordinates()); // features are parsed correctly
                });
                source.addFeatures(features);
            }
        };
        xhr.send();
    },
    url: "http://abcd.com/cities/{z}/{x}/{y}.geojson"
});
source.on("addfeature", function () {
    console.log(source.getFeatures()); // outputs an empty array of the features; it seems that the features haven't been added
});
new ol.Map({
    target: "map",
    layers: [
        new ol.layer.Vector({
            source: source
        })
    ],
    view: new ol.View({
        center: ol.proj.fromLonLat([0, 0]),
        maxZoom: 12,
        minZoom: 1,
        zoom: 6
    })
});

Any suggestions?

Best Answer

First of all, please don't use OpenLayers 3.9 and ol.source.TileVector. That has many issues. Use a recent version and ol.source.VectorTile, like in your first snippet.

If your GeoJSON has "features": null, then it is is invalid. From the GeoJSON spec:

An object of type "FeatureCollection" must have a member with the name "features". The value corresponding to "features" is an array. Each element in the array is a feature object as defined above.

So if a tile has no features, the GeoJSON for the tile should contain "features": [] instead.

If you do not have access to the server that provides the tiles, you can work around the issue on the client side:

new ol.source.VectorTile({
  format: new ol.format.GeoJSON(),
  tileGrid: ol.tilegrid.createXYZ(),
  url: "http://abcd.com/cities/{z}/{x}/{y}.geojson"
  tileLoadFunction: function(tile, url) {
    tile.setLoader(function() {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.onload = function() {
        var json = JSON.parse(xhr.responseText);
        if (json.features === null) {
          json.features = [];
        }
        var features = tile.getFormat().readFeatures(json, {featureProjection: map.getView().getProjection()});
        tile.setFeatures(features);
      }
      xhr.send();
    })
  }
})