3

I'm trying to use a GeoJSON to build a layer on an OpenLayers map of MultiPolygons from my PostGIS database.

However the following error is thrown:

Uncaught Error: Unsupported GeoJSON type: undefined

b_                     GeoJSON.js:323
readFeatureFromObject  GeoJSON.js:113
readFeaturesFromObject GeoJSON.js:157
readFeatures           JSONFeature.js:54
<anonymous>            prova.js:19

I've already tried to check the GeoJSON on GeoJSONlint as suggested here, but it gives right hand rule error. I've tried to fix this usingthis solution, but the error was in my coordinates, as @pavlos noted and corrected.

I've also tried to correct the feature projection, but the error persist.

This is the PHP script that is called by AJAX:

<?php
    $conn = pg_connect("host=localhost port=5432 user=postgres password=root dbname=benilun");
    if (!$conn) {
        die("Connessione PostgreSQL fallita.");
    };
    $res = pg_query($conn, "SELECT json_build_object( 'type', 'FeatureCollection', 'features', json_agg(ST_AsGeoJSON(t.*)::json) )
FROM ( SELECT id, identificazione, area FROM luogo ) as t(id, name, geom);");
    echo json_encode(pg_fetch_row($res));
?>

This is the JavaScript which should build the OpenLayers map; I've updated it with a @JGH suggestion, that doesn't change the error but is indeed more correct:

var res;
var dati = new FormData();
$.ajax({
    url: "php/prova.php",
    type: "POST",
    data: dati,
    success: function (resJ) {
        res = JSON.parse(resJ);
        var vectorSource = new ol.source.VectorSource({
          features: new ol.format.GeoJSON().readFeatures(res, {featureProjection: 'EPSG:3857'})
        });
        var stile = new ol.style.Style({
            stroke: new ol.style.Stroke({
              color: 'red',
              width: 1,
            }),
            fill: new ol.style.Fill({
              color: 'rgba(255, 0, 0, 0.1)',
            }),
        });
        var vectorLayer = new ol.layer.VectorLayer({
          source: vectorSource,
          style: stile
        });
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                vectorLayer
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([15, 15]),
                zoom: 4
            })
        });
    },
    cache: false,
    contentType: false,
    processData: false
});

And this is the GeoJSON object that is sent as response to the AJAX interrogation (suggested by @TomazicM, in the last edit I forgot the object):

{
  "type" : "FeatureCollection",
  "features" : [{
    "type": "Feature",
    "geometry": {
      "type":"MultiPolygon",
      "coordinates":[[[[10,30],[30,30],[30,60],[10,10],[10,30]]]]
    },
    "properties": {"id": 1, "name": "Parrocchia Santa Caterina"}
  }]
}

Could you help me?

8
  • This does not look valid [[[[10,30],[10,10],[10,30],[30,10],[10,30]]]] with 1st and 3rd vertex both being (10,30).
    – user30184
    Feb 18, 2022 at 18:12
  • Thanks @user30184 , I've corrected the points but the error still persist.
    – DandozWar
    Feb 18, 2022 at 18:20
  • 1
    Please edit your question and put back GeoJSON data sample that you removed on your last edit.
    – TomazicM
    Feb 19, 2022 at 11:36
  • I think your coordinates is the problem. Try to change this --> "coordinates":[[[[10,30],[30,30],[30,10],[10,10],[10,30]]]] to this --> "coordinates":[[[[10,30],[30,30],[30,60],[10,10],[10,30]]]]. Consider that to shape a polygon you have to respect the right hand rule.
    – pavlos
    Feb 19, 2022 at 20:57
  • 1
    @DandozWar are you sure it is only the object and not an array with one object? pg_fetch_row returns an array with each column, so i think your api returns an array. You can try to add console.log(Array.isArray(res)); and see if it is true. You can also just add res = res[0]; after res = JSON.parse(resJ); and see if it works.
    – Dataform
    Feb 20, 2022 at 15:06

2 Answers 2

3

JavaScript will not wait for the ajax call to return before continuing processing your code. The only thing that will happen once the Ajax call is completed is success: function (resJ) { res = JSON.parse(resJ); }, but it is too late, the map is already loaded with an empty json (the initial content of restJ).

You will want to load the layer after the Ajax call is completed. You can put all the code that comes after the $.ajax({..}) (i.e. the code creating the layers, the map etc) inside a function, and call this function from within the success: section.

4
  • But async option is set to false, so that shouldn't be the reason.
    – TomazicM
    Feb 18, 2022 at 19:28
  • async: false is deprecated api.jquery.com/jquery.ajax
    – Mike
    Feb 18, 2022 at 19:29
  • @Mike Thanks for the info. I'm not JQuery user, so I trusted the code I saw. And your comment is actually answer to the question.
    – TomazicM
    Feb 18, 2022 at 20:19
  • @JGH Putting the layer creation in the success function is a good idea indeed so I've done it, but it still doesn't work and the error is the same.
    – DandozWar
    Feb 18, 2022 at 21:34
1

Thanks @Dataform comment I've finally figured out what the error was.

The type of GeoJSON was Undefined because I was passing an array cointaining the GeoJSON. In the php script the methodpg_fetch_row returns an array, in order to send the GeoJSON I have to send only its first element.

Here the corrected php script:

<?php
    $conn = pg_connect("host=localhost port=5432 user=postgres password=root dbname=benilun");
    if (!$conn) {
        die("Connessione PostgreSQL fallita.");
    };
    $res = pg_query($conn, "SELECT json_build_object( 'type', 'FeatureCollection', 'features', json_agg(ST_AsGeoJSON(t.*)::json) )
FROM ( SELECT id, identificazione, area FROM luogo ) as t(id, name, geom);");
    $obj_arr = pg_fetch_row($res);
    echo json_encode($obj_arr[0]);
?>

In addition I've corrected some more errors in the usage of OpenLayers, here the updated version of the JavaScript code:

var res;
var dati = new FormData();
$.ajax({
    url: "php/prova.php",
    type: "POST",
    data: dati,
    success: function (resJ) {
        res = JSON.parse(resJ);
        var vectorSource = new ol.source.Vector({
          features: new ol.format.GeoJSON().readFeatures(res, {featureProjection: 'EPSG:3857'})
        });
        var stile = new ol.style.Style({
            stroke: new ol.style.Stroke({
              color: 'red',
              width: 1,
            }),
            fill: new ol.style.Fill({
              color: 'rgba(255, 0, 0, 0.1)',
            }),
        });
        var vectorLayer = new ol.layer.Vector({
          source: vectorSource,
          style: stile
        });
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                vectorLayer
            ],
            view: new ol.View({
                padding: [40, 40, 40, 40]
            })
        });
        
        map.getView().fit(vectorSource.getExtent())
    },
    cache: false,
    contentType: false,
    processData: false
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.