在Python中将嵌套的JSON转换为CSV

时间:2019-04-04 07:42:45

标签: python json python-3.x

我想将嵌套的json转换为csv文件。
我正在从Rest API接收json。
csv中的字段应如下所示。
daterange_start,daterange_end,点击次数,展示次数,数据透视值。
我是Python和JSON的新手,所以希望获得一些帮助。
这是示例json。

HERE is my KO.JS

```````````````````````````````````````````



// Declare function contain object info as a storage for json items
function locationInfo(info) {
  var self = this;
  self.name = info.name;
  self.location = info.location;
  self.photo = info.photos;
  self.contact = info.contact;
  self.id = info.id;
  self.categories = info.categories;
  self.address = info.location.formattedAddress;

}




function ViewModel() {

  var self = this;

  // Constructor creates a new map - only center and zoom are defined.
  self.map = new google.maps.Map(document.getElementById('map'), {
  center: {lat: 32.7761827, lng:  -96.7995296},
  zoom: 11

    });
/*  
  self.infowindow = new google.maps.InfoWindow({
    content: document.getElementById('popupinfo')
    });
*/
  // declare infowindow instances **
  self.largeInfowindow = new google.maps.InfoWindow(); 
  self.bounds = new google.maps.LatLngBounds();
//
  autocomplete = new google.maps.places.Autocomplete((document.getElementById('places-search')),
        {
            types: ['(cities)']
        }

    );
    self.places = new google.maps.places.PlacesService(self.map);
    google.maps.event.addListener(autocomplete, 'place_changed', searchBoxPlaces);  

  // Using google street view
  self.streetViewService = new google.maps.StreetViewService();
  // defined radius for 50 miles
  self. radius = 50;

  // define the location array using knockout observable array
  self.locations = ko.observableArray([]);

  // define markers for each location using knockout obseravble array
  self.markers = ko.observableArray([]);

  // define filter input text using knockout observable function
  self.filter = ko.observable();
 // self.cityName = document.getElementById('places-search').value;



  function searchBoxPlaces() {

    self.place = autocomplete.getPlace();
        if (self.place.length == 0) {
          window.alert('We did not find any places matching that search!');
        } else {
        // For each place, get the icon, name and location.
        self.map.panTo(self.place.geometry.location);
        self.map.setZoom(13);

        }
  self.cityName = self.place.address_components[0].long_name;
  //console.log(self.cityName);  
  self.url = "https://api.foursquare.com/v2/venues/search?client_id=NQM5SU1P2NFO2T05ICZFQBZDSZPHOGEDSSY2ABR4YOL1BZ43&client_secret=2ESR3ZZPIGATWXAIZ4UF5P2EPHHAITWVA4WEWYLNEGRINBRE&v=20180323&limit=5&near=" + self.cityName + "&query=bank";
  // getJson information from foursquare api
  $.getJSON(self.url, function(data) {
      // listLocation will hold the array value of 
      //each mapped object and its object property value >>(function items)
      let listLocations = $.map(data.response.venues, function(items){

      return new locationInfo(items);
      //console.log(locationInfo);
      });
      //using knock out to store locations
      self.locations(listLocations);
      //console.log(self.locations);
  }).error ( function (e){
      $(".bank-list").hide();
      $(".locationsErrorHandling").show();

  });

  }

  // Create marker Object function which we will pass in a knockout location array property
  // when function is called to create a marker object location  
  self.markerOjbectCreated =  function (location){

    let marker = new google.maps.Marker({
                map: self.map,
                position: location.location,
                title: location.name,
                id: location.id,
                desc: location.desc,
                animation: google.maps.Animation.Drop,
                display: location.display
            });
        return marker;
  };

  // creating object function allows to binding between the list and pop up info window
  self.selectedLocation = function (clickedLocation){
      if ( clickedLocation instanceof locationInfo) {
          for ( let i = 0; i < self.markers().length; i++){
              // if the clicked name is matching with marker name then set it to marker
              if (clickedLocation.name = self.markers()[i].name){
                  clickedLocation = self.markers()[i];
              }
          }
      }
      // Force marker unbounce
      self.toggleUnbounce(self.markers());
      //Marker bounce when venues's name clicked
      self.toggleBounce(clickedLocation);
      // Then popup window will opened up
      self.populateInfoWindow(clickedLocation, self.largeInfowindow);
  };

  // comparing strings object function
  self.stringStartWith = function ( string, startsWith){
      string = string || "";
      if (startsWith.length > string.length)
          return false;
      else 
          return string.substring(0,startsWith.length) == startsWith;
  };

    // Populate markers on map with this OF
  self.displayMarkersLocation = function (markers) {
      //console.log(markers);
      for (let i = 0; i < markers.length; i++){
          markers[i].setMap(self.map);
        self.bounds.extend(markers[i].position);
      }
      self.map.fitBounds(self.bounds);
  };

   // clear marker before search marker pop up
 self.clearMarkers = function(markers) {

    for (var i = 0; i < self.markers.length; i++) {
        if (markers[i]) {
            markers[i].setMap(null);
        }
    }
    self.markers = [];

}; 
  // show markers
  self.showMarker = function ( marker) {
     marker.setMap(self.map);
     self.bounds.extend(marker.position);
     self.map.fitBounds(self.bounds);
  };



  // Hide markers
  self.hideMarkers = function ( markers) {
      for (let i = 0; i < markers.length; i++){
          markers[i].setMap(null);
      }
  };

   // Filter text items
  self.filteredBank = ko.computed( function(){
    let filter = self.filter();

    let startsWith = false;
    if (!filter) {
      self.displayMarkersLocation(self.markers());
      return self.locations();    
    }else { 
    self.hideMarkers(self.markers());
       return ko.utils.arrayFilter(self.markers(), function(marker){
        startsWith = marker.title.toLowerCase().indexOf(filter.toLowerCase()) !==-1;
          if (startsWith){
            self.showMarker(marker);
            return true;
          }
       });
    }

  }, self);


  // Marker Bouncing Function
 self.toggleBounce  = function (marker){
     if(marker.getAnimation() !== null){
         marker.setAnimation(null);
     } else {
         marker.setAnimation(google.maps.Animation.BOUNCE);
     }
 };


  // Marker unbounce Function
  self.toggleUnbounce = function (markers){
      for ( let i = 0; i < markers.length; i++){
          if (markers[i].getAnimation() !== null){
              markers[i].setAnimation(null);
          }
      }
  };

  self.populateInfoWindow = function (marker, infowindow){
            // first we need to check to make sure the infowindow is not already opened on this marker.
    if (infowindow.marker != marker){ // if info window not set to marker then
        infowindow.setContent(''); // then use setContent function to html div and pass in marker title
        infowindow.marker = marker; //  set infowindow marker to marker
        // then use open method to open it
        // make sure the marker property is cleared if the infowindow is closed.
        // why? is it going to display on next window?
        infowindow.addListener('closeclick', function(){
            self.toggleUnbounce(self.markers());
            infowindow.setMarker = null; // using setMarker function to null to clear marker info.

        });
        // we need to instancitate the streetViewService method from google maps 
        // if we can't find exact location then define radius of 50 meter nearby area
        let streetViewService = new google.maps.StreetViewService();
        let radius = 50;
          // In case the status is OK, which means the pano was found, compute the
          // position of the streetview image, then calculate the heading, then get a
          // panorama from that and set the options
        let  getStreetView = function(data, status) {
            if (status == google.maps.StreetViewStatus.OK) {
                let nearStreetViewLocation = data.location.latLng; // load geometry library
                let heading = google.maps.geometry.spherical.computeHeading(
                nearStreetViewLocation, marker.position);
                infowindow.setContent('<div>'+ '<h3>' + marker.title + '</h3>' + '</div>' +
                 '<div id="pano"></div>' + '<div>' + '<p>' + marker.address + '</p>' +
                 '<p>' + marker.desc + '</p>' + '</div>' );
                let panoramaOptions = { // set panarama option
                  position: nearStreetViewLocation,
                  pov: {
                    heading: heading,
                    pitch: 30
                  }
                };
                let panorama = new google.maps.StreetViewPanorama( // create panarama image and pass it into id pano
                document.getElementById('pano'), panoramaOptions);
            } 
            else {
              infowindow.setContent('<div>'+ '<h3>' + marker.title + '</h3>' + '</div>' +
                '<div>No Street View Found</div>');
            }
        };
        // Use streetview service to get the closest streetview image within
        // 50 meters of the markers position, pass into this function with marker position
        // radius and function getStreetView to the getPanoramaByLocation function.
        self.streetViewService.getPanoramaByLocation(marker.position, self.radius, getStreetView);
         // Open the infowindow on the correct marker.
        infowindow.open(self.map, marker);  

    }

  };


  self.mapLoading = ko.computed (function () {

      let locations = self.locations();
      //console.log(locations);
      //let markers = self.markers();
      //console.log(markers);

      let largeInfowindow = self.largeInfowindow;
      let bounds = self.bounds;

      let clickMarkerWindow = function ( marker, largeInfowindow){
          marker.addListener('click', function () {
              self.toggleUnbounce(self.markers());
              self.toggleBounce( this);
              self.populateInfoWindow(this, largeInfowindow);
          });
      };

      // now we use knock out array to create array when the map is loading
      for (let i = 0; i < locations.length; i++){
          let marker = self.markerOjbectCreated(locations[i]);
          // store markers in knockout marker arrray
          self.markers().push(marker);
          // allow popup window to open when marker is clicking with OF defined aboveed
          clickMarkerWindow(marker, largeInfowindow);
          // recenter bound map to that location 
          bounds.extend(self.markers()[i].position);
      } // End of forloop

      // Extend map to cover all markers 
      self.map.fitBounds(bounds);

      $(window).resize(function() {
          google.maps.event.addDomListener(window, 'resize', function() {
              self.map.fitBounds(bounds);
          });
      });

  }, self);


  // call maploading object.
  self.mapLoading();




}

// Call back funtion to load initMap 
function initMap() {
  ko.applyBindings( new ViewModel() );
}

2 个答案:

答案 0 :(得分:1)

您可以使用以下命令在python中加载并解析json:

import json
y = json.loads(x)

y将是python字典。现在,在y['elements']上循环并创建一个包含所需字段的列表。例如,提取开始日期和结束日期的年份:

list_for_csv=[]
for e in y['elements']:
    list_for_csv.append([e['daterange']['start']['year'],e['daterange']['end']['year']])

然后使用numpy将其另存为csv:

import numpy as np
for_csv = np.asarray(list_for_csv)
np.savetxt("your_file.csv", for_csv, delimiter=",")

答案 1 :(得分:1)

您可以使用json_normalize。唯一的问题是"pivotValues"是一个列表。因此,不确定要在那里保存的内容,或者这些列表中是否包含1个以上的元素。如果只是一个元素,则可以轻松地处理该列。如果它可以包含多个元素,则可以为每个元素创建一个新行(这意味着您有多个具有相同数据的行,但不同的pivotValues除外,也可以扩展每一行以使每个pivotValues ,但这些列表的长度为null时长度会不同。

我还在那里添加了代码(看到pivotValues都具有相同的前缀),以防您需要帽子值。

给出:

data = {
    "elements": [
        {
            "dateRange": {
                "start": {
                    "month": 3,
                    "year": 2019,
                    "day": 3
                },
                "end": {
                    "month": 3,
                    "year": 2019,
                    "day": 3
                }
            },
            "clicks": 11,
            "impressions": 2453,
            "pivotValues": [
                "urn:li:sponsoredCampaign:1234567"
            ]
        },
        {
            "dateRange": {
                "start": {
                    "month": 3,
                    "year": 2019,
                    "day": 7
                },
                "end": {
                    "month": 3,
                    "year": 2019,
                    "day": 7
                }
            },
            "clicks": 1,
            "impressions": 629,
            "pivotValues": [
                "urn:li:sponsoredCampaign:1234565"
            ]
        },
        {
            "dateRange": {
                "start": {
                    "month": 3,
                    "year": 2019,
                    "day": 21
                },
                "end": {
                    "month": 3,
                    "year": 2019,
                    "day": 21
                }
            },
            "clicks": 3,
            "impressions": 154,
            "pivotValues": [
                "urn:li:sponsoredCampaign:1323516"
            ]
        }
    ],
    "paging": {
        "count": 10,
        "start": 0,
        "links": []
    }
}

代码:

import pandas as pd
from pandas.io.json import json_normalize


df = json_normalize(data['elements'])
df['pivotValues'] = df.pivotValues.apply(pd.Series).add_prefix('pivotValues_')
df['pivotValues_stripped'] = df['pivotValues'].str.rsplit(':',1, expand=True)[1]

df.to_csv('path/filename.csv', index=False)

输出:

print (results.to_string())
   clicks  dateRange.end.day  dateRange.end.month  dateRange.end.year  dateRange.start.day  dateRange.start.month  dateRange.start.year  impressions                       pivotValues pivotValues_stripped
0      11                  3                    3                2019                    3                      3                  2019         2453  urn:li:sponsoredCampaign:1234567              1234567
1       1                  7                    3                2019                    7                      3                  2019          629  urn:li:sponsoredCampaign:1234565              1234565
2       3                 21                    3                2019                   21                      3                  2019          154  urn:li:sponsoredCampaign:1323516              1323516