gtt-project/redmine_gtt

projects.json endpoint should return "geojson" property as GeoJSON object

sanak opened this issue · 7 comments

sanak commented

Problem
After PR: #202, /projects.json returns geojson property as string (geojson:"{.....}"), but it should be GeoJSON object (geojson:{.....}).

To Reproduce
Access to http://localhost:3000/projects.json?include=geometry.

Expectation
It should return GeoJSON object (geojson:{.....}).

sanak commented

This seems to be the original behavior from the very beginning, and I guess that the reason is that the tests are using xml format, and in that case, geojson property needs to be string type.
https://github.com/gtt-project/redmine_gtt/search?q=geojson.to_json&type=code

Could the tests be adjusted? Let's say convert the JSON to text for that attribute for that test?

It's definitely not so difficult for client apps to turn text to JSON, but it doesn't feel like right ... if it's actually possible to return JSON.

sanak commented

Oh, yes. I am thinking to adjust the test side.

Using JSON object is possible, but I noticed that project.xml format result was strange (Ruby hash map operator => is used)...

<project>
<id>1</id>
<name>Test Project</name>
<identifier>test-project</identifier>
<description/>
<homepage/>
<status>1</status>
<is_public>true</is_public>
<geojson type="Feature" geometry="{"type"=>"MultiPolygon", "coordinates"=>[[[[140.28939099086716, 35.570678641254645], ...]]]}" properties="{}"/>
:

So, I am thinking to return JSON object for /projects.json?... request, but return string for /projects.xml request.

That makes sense, because it makes no sense to change GeoJSON into XML format.

sanak commented

Okay, thanks for confirmation! 🙇‍♂️
I will take a look at it.

sanak commented

The following empty string issue is also related with this issue. (It should return null for .json, but "" in .xml)
#171

sanak commented

Well, from local trial, the following diff seems to realize above specs.

--- a/app/views/projects/index.api.rsb
+++ b/app/views/projects/index.api.rsb
@@ -11,9 +11,10 @@ api.array :projects, api_meta(:total_count => @project_count, :offset => @offset
 
       if @include_geometry
         if project.geom
-          api.geojson project.geojson.to_json
+          api.geojson (params[:format] == "json") ? project.geojson : project.geojson.to_json
         else
-          api.geojson ""
+          #api.geojson (params[:format] == "json") ? nil : ""
+          api.geojson nil
         end
       end

Here is above result:

JSON output

{
    "projects": [
        {
            "id": 1,
            "name": "TEST",
            "identifier": "test",
            "description": "",
            "status": 1,
            "is_public": true,
            "geojson": {
                "type": "Feature",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [
                        [
                            [
                                139.674126132,
                                35.688586166
                            ],
                            [
                                139.700386299,
                                35.707467078
                            ],
                            [
                                139.727988241,
                                35.699185447
                            ],
                            [
                                139.729617683,
                                35.67577344
                            ],
                            [
                                139.6912688,
                                35.674467215
                            ],
                            [
                                139.674126132,
                                35.688586166
                            ]
                        ]
                    ]
                },
                "properties": {}
            },
            "created_on": "2021-05-21T14:46:45Z",
            "updated_on": "2021-05-21T14:47:08Z"
        },
        {
            "id": 2,
            "name": "TEST2",
            "identifier": "test2",
            "description": "",
            "status": 1,
            "is_public": true,
            "geojson": null,
            "created_on": "2023-01-03T13:53:49Z",
            "updated_on": "2023-01-03T13:53:49Z"
        }
    ],
    "total_count": 2,
    "offset": 0,
    "limit": 25
}

XML output

<?xml version="1.0" encoding="UTF-8"?>
<projects total_count="2" offset="0" limit="25" type="array">
    <project>
        <id>1</id>
        <name>TEST</name>
        <identifier>test</identifier>
        <description></description>
        <status>1</status>
        <is_public>true</is_public>
        <geojson>{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[139.674126132,35.688586166],[139.700386299,35.707467078],[139.727988241,35.699185447],[139.729617683,35.67577344],[139.6912688,35.674467215],[139.674126132,35.688586166]]]},"properties":{}}</geojson>
        <created_on>2021-05-21T14:46:45Z</created_on>
        <updated_on>2021-05-21T14:47:08Z</updated_on>
    </project>
    <project>
        <id>2</id>
        <name>TEST2</name>
        <identifier>test2</identifier>
        <description></description>
        <status>1</status>
        <is_public>true</is_public>
        <geojson/>
        <created_on>2023-01-03T13:53:49Z</created_on>
        <updated_on>2023-01-03T13:53:49Z</updated_on>
    </project>
</projects>

In case of empty geojson string in xml format, api.geojson = "" generates <geojson></geojson> and api.geojson = nil generates <geojson/>.
But those are same meaning in xml format, so just set nil seems to be enough.