title: Converting JSON to QGIS GeoJSON: while having multiple features and different types
body: <p>Currently I have a program that request JSONS from specific API. The creators of the API have claimed this data is in GeoJSON but QGIS cannot read it.</p>
  <p>So I want to extend my Python Script to converting the JSON to GEOJSON in a readable format to get into QGIS and process it further there.</p>
  <p>However, I have a few problems,
  one I do not know where to start and How the JSON files are constructed...its kind of mess. The JSONS were actually maded based on two API Get Request. One Api Get Request request the Points and the second one requests the details of the points. See this question here for some more context:
  <a href="https://stackoverflow.com/questions/66152751/api-request-within-another-api-request-same-api-in-python/66153040?noredirect=1#comment116958447_66153040">API Request within another API request (Same API) in Python</a></p>
  <p>Note because of character limit I cannot post the code here:</p>
  <p>These details are of course supposed to be &quot;the contours&quot; of the area surrounding these points.
  The thing is..the point itself is mentioned in the JSON, making it kind of hard to specify what coordinate is for each point. Not to mention all other attributes that are intresting to us, are in the &quot;point&quot; part of the GeoJSON.</p>
  <p>Take a look at the JSON itself to see what I mean:</p>
  <pre><code>{
      &quot;comment&quot;: null,
      &quot;contactDetails&quot;: {
          &quot;city&quot;: null,
          &quot;country&quot;: &quot;BE&quot;,
          &quot;email&quot;: null,
          &quot;extraAddressInfo&quot;: null,
          &quot;firstName&quot;: null,
          &quot;kboNumber&quot;: null,
          &quot;lastName&quot;: &quot;TMVW&quot;,
          &quot;number&quot;: null,
          &quot;organisation&quot;: &quot;TMVW - Brugge-Kust&quot;,
          &quot;phoneNumber1&quot;: null,
          &quot;phoneNumber2&quot;: null,
          &quot;postalCode&quot;: null,
          &quot;street&quot;: null
      },
      &quot;contractor&quot;: null,
      &quot;description&quot;: &quot;WEGENISWERKEN - Oostende - 154-W - H Baelskaai-project Oosteroever&quot;,
      &quot;diversions&quot;: [],
      &quot;endDateTime&quot;: &quot;2021-06-30T00:00:00&quot;,
      &quot;gipodId&quot;: 1042078,
      &quot;hindrance&quot;: {
          &quot;description&quot;: null,
          &quot;direction&quot;: null,
          &quot;effects&quot;: [
              &quot;Omleiding: beide richtingen&quot;,
              &quot;Afgesloten: volledige rijweg&quot;,
              &quot;Fietsers hebben geen doorgang&quot;,
              &quot;Handelaars bereikbaar&quot;,
              &quot;Plaatselijk verkeer: toegelaten&quot;,
              &quot;Voetgangers hebben doorgang&quot;
          ],
          &quot;important&quot;: true,
          &quot;locations&quot;: [
              &quot;Voetpad&quot;,
              &quot;Fietspad&quot;,
              &quot;Parkeerstrook&quot;,
              &quot;Rijbaan&quot;
          ]
      },
      &quot;latestUpdate&quot;: &quot;2020-12-01T12:16:00.03&quot;,
      &quot;location&quot;: {
          &quot;cities&quot;: [
              &quot;Oostende&quot;
          ],
          &quot;coordinate&quot;: {
              &quot;coordinates&quot;: [
                  2.931988215468502,
                  51.23633810341717
              ],
              &quot;crs&quot;: {
                  &quot;properties&quot;: {
                      &quot;name&quot;: &quot;urn:ogc:def:crs:OGC:1.3:CRS84&quot;
                  },
                  &quot;type&quot;: &quot;name&quot;
              },
              &quot;type&quot;: &quot;Point&quot;
          },
          &quot;geometry&quot;: {
              &quot;coordinates&quot;: [
                  [
                      [
                          2.932567101705748,
                          51.23657315009855
                      ],
                      [
                          2.9309934586397337,
                          51.235776874431004
                      ],
                      [
                          2.9328606392338914,
                          51.2345112414401
                      ],
                      [
                          2.9344086040607285,
                          51.23535468563417
                      ],
                      [
                          2.9344709862243095,
                          51.23529463700852
                      ],
                      [
                          2.932928489694045,
                          51.23447026126373
                      ],
                      [
                          2.935453674897618,
                          51.2326691257775
                      ],
                      [
                          2.937014893295095,
                          51.23347469462423
                      ],
                      [
                          2.9370649363167556,
                          51.23342209549579
                      ],
                      [
                          2.9355339718818847,
                          51.23261689467634
                      ],
                      [
                          2.937705787093551,
                          51.23108125372614
                      ],
                      [
                          2.939235922008332,
                          51.23191301940206
                      ],
                      [
                          2.9393162149112086,
                          51.231860784836144
                      ],
                      [
                          2.9377921292631313,
                          51.23102909334536
                      ],
                      [
                          2.9395494398210404,
                          51.22978103014327
                      ],
                      [
                          2.9395326861153492,
                          51.22973522407282
                      ],
                      [
                          2.9307116955342982,
                          51.23588365892173
                      ],
                      [
                          2.93077732400986,
                          51.235914858980586
                      ],
                      [
                          2.930921969180147,
                          51.23581685905391
                      ],
                      [
                          2.932475593354336,
                          51.23662429379119
                      ],
                      [
                          2.932567101705748,
                          51.23657315009855
                      ]
                  ]
              ],
              &quot;crs&quot;: {
                  &quot;properties&quot;: {
                      &quot;name&quot;: &quot;urn:ogc:def:crs:OGC:1.3:CRS84&quot;
                  },
                  &quot;type&quot;: &quot;name&quot;
              },
              &quot;type&quot;: &quot;Polygon&quot;
          }
      },
      &quot;mainContractor&quot;: null,
      &quot;owner&quot;: &quot;TMVW - Brugge-Kust&quot;,
      &quot;reference&quot;: &quot;DOM-154/15/004-W&quot;,
      &quot;startDateTime&quot;: &quot;2017-05-02T00:00:00&quot;,
      &quot;state&quot;: &quot;In uitvoering&quot;,
      &quot;type&quot;: &quot;Wegeniswerken (her)aanleg&quot;,
      &quot;url&quot;: null
  }
  </code></pre>
  <p>As a reminder these JSON's are not supposed to be point files and the geometry can be either a polygon as seen above: A multipolygon or a multiLinestring (do not have an example here).</p>
  <p><strong>So how do I get started and make sure I not only get the detail attributes out but clearly the contour geometry and coordinates?</strong></p>
  <p>The only Unique id is the GIPOD ID, because this one is where the actual link in this API database is.</p>
  <p>Edit 1:</p>
  <p>So this is the supposed geojson standard.</p>
  <pre><code>{
    &quot;type&quot;: &quot;Feature&quot;,
    &quot;geometry&quot;: {
      &quot;type&quot;: &quot;Point&quot;,
      &quot;coordinates&quot;: [125.6, 10.1]
    },
    &quot;properties&quot;: {
      &quot;name&quot;: &quot;Dinagat Islands&quot;
    }
  }
  </code></pre>
  <p>Based on this standard, the converted JSON should be this:</p>
  <pre><code>    &quot;type&quot;: &quot;Feature&quot;,
                 &quot;geometry&quot;: {
                     &quot;type&quot;: &quot;Polygon&quot;,
                     &quot;coordinates&quot;: [
                      [
                          [
                              2.932567101705748,
                              51.23657315009855
                          ],
                          [
                              2.9309934586397337,
                              51.235776874431004
                          ],
                          [
                              2.9328606392338914,
                              51.2345112414401
                          ],
                          [
                              2.9344086040607285,
                              51.23535468563417
                          ],
                          [
                              2.9344709862243095,
                              51.23529463700852
                          ],
                          [
                              2.932928489694045,
                              51.23447026126373
                          ],
                          [
                              2.935453674897618,
                              51.2326691257775
                          ],
                          [
                              2.937014893295095,
                              51.23347469462423
                          ],
                          [
                              2.9370649363167556,
                              51.23342209549579
                          ],
                          [
                              2.9355339718818847,
                              51.23261689467634
                          ],
                          [
                              2.937705787093551,
                              51.23108125372614
                          ],
                          [
                              2.939235922008332,
                              51.23191301940206
                          ],
                          [
                              2.9393162149112086,
                              51.231860784836144
                          ],
                          [
                              2.9377921292631313,
                              51.23102909334536
                          ],
                          [
                              2.9395494398210404,
                              51.22978103014327
                          ],
                          [
                              2.9395326861153492,
                              51.22973522407282
                          ],
                          [
                              2.9307116955342982,
                              51.23588365892173
                          ],
                          [
                              2.93077732400986,
                              51.235914858980586
                          ],
                          [
                              2.930921969180147,
                              51.23581685905391
                          ],
                          [
                              2.932475593354336,
                              51.23662429379119
                          ],
                          [
                              2.932567101705748,
                              51.23657315009855
                          ]
                     ]
                 },
                 &quot;properties&quot;: {
  Too much columns to type, cannot claim them all here because of character limit.
                     }
             }
  </code></pre>
  <p>Edit 3: The Solution provided was a good step in the right direction but it gives me two problems:</p>
  <ol>
  <li>The saved geometry is Null making this JSON a table without
  geometry.</li>
  <li>Only 1 data_point is saved and not all data_points that are
  being requested.</li>
  </ol>
  <p>Here is the JSON:</p>
  <pre><code>{&quot;type&quot;: &quot;FeatureCollection&quot;, &quot;features&quot;: [{&quot;type&quot;: &quot;Feature&quot;, &quot;geometry&quot;: null, &quot;properties&quot;: {&quot;gipodId&quot;: 3099549, &quot;StartDateTime&quot;: null, &quot;EndDateTime&quot;: null, &quot;state&quot;: null, &quot;location&quot;: {&quot;cities&quot;: [&quot;Waregem&quot;, &quot;Wielsbeke&quot;], &quot;coordinate&quot;: {&quot;coordinates&quot;: [3.4206971887218445, 50.91662742195287], &quot;type&quot;: &quot;Point&quot;, &quot;crs&quot;: {&quot;type&quot;: &quot;name&quot;, &quot;properties&quot;: {&quot;name&quot;: &quot;urn:ogc:def:crs:OGC:1.3:CRS84&quot;}}}}}}]}
  </code></pre>
  <p>Python Code: Below to see how far it has gone:</p>
  <pre><code>import requests
  import json
  import os
  import glob
  import shutil
  
  def process_location_data(location_json): 
     &quot;&quot;&quot;Converts the data point into required geojson format&quot;&quot;&quot;
  
    
     # assigning variable to store geometry details
     geometery_details = location_json.get(&quot;location&quot;).get(&quot;geometery&quot;)
     #geometery_details.pop(&quot;crs&quot;)  # removes the &quot;crs&quot; from geometry
  
     # includes city and location_coordinates
     location_details = {
       &quot;cities&quot;: location_json.get(&quot;location&quot;).get(&quot;cities&quot;),
       &quot;coordinate&quot;: location_json.get(&quot;location&quot;).get(&quot;coordinate&quot;)
     }
  
     #EndDateTime
     end_datetime = location_json.get(&quot;EndDateTime&quot;)
  
     #StarDateTime
     start_datetime = location_json.get(&quot;StarDateTime&quot;)
  
     #State
     state = location_json.get(&quot;State&quot;)
  
     #gipodId
     gipod_id = location_json.get(&quot;gipodId&quot;)
     
     #adding all these details into another dict
     properties = {
       &quot;gipodId&quot;: gipod_id,
       &quot;StartDateTime&quot;: start_datetime,
       &quot;EndDateTime&quot;: end_datetime,
       &quot;state&quot;: state,
       &quot;location&quot;: location_details
     }
  
  
     # creating the final dict to be returned.
     geojson_data_point = {
         &quot;type&quot;: &quot;Feature&quot;,
         &quot;geometry&quot; : geometery_details,
         &quot;properties&quot;: properties
     }
  
     return geojson_data_point
  
  def process_all_location_data(all_location_points):
      &quot;&quot;&quot;
      For all the points in the location details we will  
      create the feature collection
      &quot;&quot;&quot;
  
      feature_collection = {
           &quot;type&quot;: &quot;FeatureCollection&quot;,
           &quot;features&quot;: []
      } #creates dict with zero features.
  
      for data_point in all_location_points:
          feature_collection.get(&quot;features&quot;).append(
              process_location_data(data_point)
          )
  
      return feature_collection
  
  
  def fetch_details(url: str, file_name: str):
        # Makes request call to get the data of detail
          response = requests.get(url)
          print(&quot;Sending Request for details of gpodId: &quot; + file_name)
          folder_path ='api_request_jsons/fetch_details/JSON unfiltered'
          text = json.dumps(response.json(),sort_keys=False, indent=4)
          print(&quot;Details extracted for: &quot;+ file_name)
          save_file(folder_path,file_name,text)
          return response.json()
          # save_file(folder_path,GipodId,text2)
          # any other processe
  
  def fetch_points(url: str):
         response = requests.get(url)
         folder_path ='api_request_jsons/fetch_points'
         text = json.dumps(response.json(),sort_keys=False, indent=4)
         print(&quot;Points Fetched, going to next step: Extracting details&quot;)
         for obj in response.json():
           all_location_points = [fetch_details(obj.get(&quot;detail&quot;),str(obj.get(&quot;gipodId&quot;)))]
         save_file(folder_path,'points',text)
         feature_collection_json = process_all_location_data(all_location_points)
         text2 = json.dumps(process_all_location_data(all_location_points))
         folder_path2 = &quot;api_request_jsons/fetch_details/Coordinates&quot;
         file_name2 = &quot;Converted&quot;
         save_file(folder_path2,file_name2,text2)
         return feature_collection_json
  
  def save_file(save_path: str, file_name: str, file_information: str):
          completeName = os.path.join(save_path, file_name +&quot;.json&quot;)
          print(completeName + &quot; saved&quot;)
          file1 = open(completeName, &quot;wt&quot;)
          file1.write(file_information)
          file1.close()
  
  api_response_url = &quot;http://api.gipod.vlaanderen.be/ws/v1/workassignment&quot;
  fetch_points(api_response_url)
  </code></pre>