1

I have a ASP.NET MVC web application that creates some GeoJSON files depending on client input and saves these files on a published folder on server. These files are to be vector data sources for an OpenLayers map on client side. I use a loop for this purpose to populate a JavaScript array and give this array to map object :

        for (let i = 0; i < dataSources.length; i++) {
            var ds = new ol.source.Vector({ format: new ol.format.GeoJSON(), url: dataSources[i], });
            var st = new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#FF8000', width: 2, }) });
            var ly = new ol.layer.Vector({ source: ds, style: st });
            layerArray.push(ly);
        }

        var map = new ol.Map({
            target: 'map',
            layers: layerArray,
            view: new ol.View({ center: ol.proj.fromLonLat([@Html.ViewBag.CenterX, 
            @Html.ViewBag.CenterY]),zoom: @Html.ViewBag.MapZoom})
            });

dataSources array contains GeoJSon file names for example :

'../../Content/dd47c229.json'
'../../Content/ea977438.json'
.....
.....

I only have the first file displayed on the map and when I inspect the page I can see this error:

Uncaught SyntaxError: Unexpected token { in JSON at position 9724
at JSON.parse (<anonymous>)
at n_ (JSONFeature.js:202:25)
at n.readFeatures (JSONFeature.js:55:7)
at XMLHttpRequest.a.onload (featureloader.js:106:20)

the position of this error is always the length of the first file in dataSources array (here : dd47c229.json). It seems that ol.source.Vector constructor does not read the second file from position 0, seems it is not a new Vector object and still has previous JSON code from the first file in memory. Is it true? Any solution for this problem?

More info:to get sure that files are valid and there is no problem with files,I made a map with 3 layers,an OSM tile layer and 2 vector layers that their data sources were 2 same files as I mentioned above and it worked. So I got sure that files are valid.The code for this part is here and I commented it in my view :

        //var ds1 = new ol.source.Vector({ format: new ol.format.GeoJSON(), url: '../../Content/d3.json', });
    //var st1 = new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#FF8000', width: 2, }) });
    //var ly1 = new ol.layer.Vector({ source: ds1, style: st1 });
    //layerArray.push(ly1);

    //var ds2 = new ol.source.Vector({ format: new ol.format.GeoJSON(), url: '../../Content/d4.json', });
    //var st2 = new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#FF8000', width: 2, }) });
    //var ly2 = new ol.layer.Vector({ source: ds2, style: st2 });
    //layerArray.push(ly2);

as you can see I used different variables out of a loop for each layers and it worked properly , so I got suspected maybe there is something wrong inside the loop.I assume that in each loop iteration variables ds,st and ly become new javascript objects so ds=new ol.source.Vector gets initialized with new parameters . Is it true?

4
  • Are you really using OL2? And check if second file is valid GeoJSON.
    – TomazicM
    Commented Jan 30, 2022 at 10:21
  • I don't think you can just concatenate json files together like that
    – Ian Turton
    Commented Jan 30, 2022 at 11:51
  • 1
    @IanTurton There is no concatenation in the code above, just looping through layer source names and each time create new source and layer. I suspect concatenation might happened at the time of the source files creation.
    – TomazicM
    Commented Jan 30, 2022 at 15:41
  • TomazicM , I use OpenLayers v6.9.0 and second file is valid.I checked it in this way : I made a view containing 3 layers,OSM and 2 vector layers with 2 files as data source.I made each vector data source independently (not inside a loop) and it worked poperly. But when I put this process inside a loop with same files,face that error.this is the code that worked properly and I commented it :
    – Reza
    Commented Jan 30, 2022 at 19:46

2 Answers 2

1

For future reference,I put my recent code here that worked for me : I changed the way for populating map layers.The entire code is here :

    <script type="text/javascript">
    var dataSources = [];
    @{ 
        var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
        var dsarray = jss.Serialize(ViewBag.DataSourceCollection);
        @:[email protected](dsarray);
    }
    var haslayer =@(ViewBag.HasLayer.ToString().ToLower());
    var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Tile({ source: new ol.source.OSM(), opacity: 0.4 }),
        ],
        view:new ol.View({ projection: 'EPSG:4326', center: [@Html.ViewBag.CenterX, @Html.ViewBag.CenterY], zoom: @Html.ViewBag.MapZoom})
    });
    if (haslayer) {
        var st = new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#FF8000', width: 2, fill: new ol.style.Fill({color:'#FF8000'})}) });
        for (let i = 0; i < dataSources.length; i++) {
            var gjson = dataSources[i];
            var ds = new ol.source.Vector({
                format: new ol.format.GeoJSON(),
                //url: gjson,
                loader: function(){
                    var xhr = new XMLHttpRequest();
                    xhr.open('GET', gjson);
                    xhr.setRequestHeader("Content-Type", "application/json");
                    //xhr.responseType = 'text';

                    xhr.onload = function () {
                        if (xhr.status == 200) {
                            //var ss = xhr.responseText;
                            //var features = new ol.format.GeoJSON().readFeatures(ss);
                            //console.log(ss);
                            ds = new ol.source.Vector({ features: new ol.format.GeoJSON({ dataProjection: 'EPSG:4326' }).readFeatures(xhr.responseText), });
                        }
                    };
                    xhr.send();
                },
            });

            var ly = new ol.layer.Vector({
                source: ds,
                displayInLayerSwitcher: false,
                style: st,
                projection:'EPSG:4326'
            });

            map.addLayer(ly);
        }
    }

</script>

I overloaded loader property of vector data source (using XMLHttpRequest) by a simple function and add each layer to map using addLayer method of map object instead of populating an array object before creating map object as TomazicM suggested in his code.This solution worked for me.I calculate map center and bounding box (and resulting zoom level)while creating geojson files and pass these parameters to view via ViewBag.

1
  • That's interesting. If @Mike comes around, he might have explanation why default loader does not work for you.
    – TomazicM
    Commented Feb 2, 2022 at 18:20
0

Since I couldn't replicate the behavior you described, this answer will be a shot in the dark.

The problem might be in the way you create vector layers. It's done in a loop and layer sources are each time assigned to the same variable. Since actual data load happens at the time of adding layer to the map, that might somehow be the problem (I'm not that much of a JS expert).

So try with this code:

var st = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: '#FF8000',
    width: 2
  })
});

for (let i = 0; i < dataSources.length; i++) {
  layerArray.push(
    new ol.layer.Vector({
      source: new ol.source.Vector({
        format: new ol.format.GeoJSON(),
        url: dataSources[i]
      }),
      style: st
    })
  );
}
6
  • I changed the code according to above suggestion exactly but it didn't worked unfortunately
    – Reza
    Commented Jan 31, 2022 at 8:11
  • Changed answer a bit. Try this one.
    – TomazicM
    Commented Jan 31, 2022 at 8:23
  • No success with latest change.Still same error.When I put a break at the end of loop and code inside loop gets executed once , everything's well without error.But in the second iteration(without break) JSONFeature object. throws this error --->Uncaught SyntaxError: Unexpected token { in JSON at position 9724 at JSON.parse (<anonymous>) at n_ (JSONFeature.js:202:25) at n.readFeatures (JSONFeature.js:55:7) at XMLHttpRequest.a.onload (featureloader.js:106:20)------>when 9724 is exactly the first file length and second file starts with this character {.
    – Reza
    Commented Jan 31, 2022 at 15:09
  • Have you tried changing order of input files?
    – TomazicM
    Commented Jan 31, 2022 at 15:22
  • 1
    this page gis.stackexchange.com/questions/422427/… shows how to use loader parameter in Vector source object,but I'm not so skilled in javascript and progress is slow :) . Maybe if I use XHR object in loader function I can reset it after loading each file. what do you think about this way?right way?
    – Reza
    Commented Jan 31, 2022 at 16:03

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.