How to split and create single objects in json? [closed]

随声附和 提交于 2020-03-23 12:05:53

问题


The following

$.ajax({
    url: "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv",
    success: function(csv) {
        const output = Papa.parse(csv, {
          header: true, // Convert rows to Objects using headers as properties
        });
        if (output.data) {
          console.log(output.data);
        } else {
          console.log(output.errors);
        }
    },
    error: function(jqXHR, textStatus, errorThrow){
        console.log(textStatus);
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>

Gives

[
  {
    "Province/State": "Anhui",
    "Country/Region": "Mainland China",
    "Lat": "31.8257",
    "Long": "117.2264",
    "1/22/20": "1",
    "1/23/20": "9",
    "1/24/20": "15",
    "1/25/20": "39",
    "1/26/20": "60",
    "1/27/20": "70",
    "1/28/20": "106",
    "1/29/20": "152",
    "1/30/20": "200",
    "1/31/20": "237",
    "2/1/20": "297",
    "2/2/20": "340",
    "2/3/20": "408",
    "2/4/20": "480",
    "2/5/20": "530"
  },
  {
    "Province/State": "Beijing",
    "Country/Region": "Mainland China",
    "Lat": "40.1824",
    "Long": "116.4142",
    "1/22/20": "14",
    "1/23/20": "22",
    "1/24/20": "36",
    "1/25/20": "41",
    "1/26/20": "68",
    "1/27/20": "80",
    "1/28/20": "91",

But the dates are single objects that I need and the number next to it too, so I'd need something like

{
  "Province/State": "Beijing",
  "Country/Region": "Mainland China",
   "Lat": "40.1824",
   "Long": "116.4142",
   "cases": [
    {
      "date": "1/28/20",
       "people": "91",
      ],
      "date": "1/29/20",
       "people": "99",
      ],
      "date": "1/30/20",
       "people": "101",
      ],
    },

Literally I'm looking for a properly formatted json with single objects


回答1:


You cannot have multiple properties with the same name like this:

{
  "date": {["1/22/20", "people": "22]"},
  "date": {["1/23/20", "people": "45]"}
}

Plus, ["people": "45"] is not valid JSON. Only the last one declared would exist in the end. But you could do this:

{
   "Province/State": "Beijing",
   "Country/Region": "Mainland China",
   "Lat": "40.1824",
   "Long": "116.4142",
   "dataset":[
     {"date": "1/22/20", "people": 22},
     {"date": "1/23/20", "people": 45}
   ]
}

$.ajax({
    url: "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv",
    success: function(csv) {
        const output = Papa.parse(csv, {
          header: true, // Convert rows to Objects using headers as properties
          dynamicTyping: true, // Convert some fields to Numbers automatically
        });
        if (output.data) {
          const formatted = output.data.map(area => {
            const obj = { dataset: [] };

            Object.keys(area).forEach(key => {
              if (/^\d+\/\d+\/\d+$/.test(key)) {
                obj.dataset.push({ date: key, people: area[key] });
              } else {
                obj[key] = area[key];
              }
            });

            return obj;
          });
          
          document.body.innerHTML = `<pre>${JSON.stringify(formatted, 0, 2)}</pre>`;
        } else {
          console.log(output.errors);
        }
    },
    error: function(jqXHR, textStatus, errorThrow){
        console.log(textStatus);
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>



回答2:


You want to separate out the comma-separated lines into

(1) labels for the object (items 0-4)

(2) number of people (items 5+)

When iterating over a line, slice the label values off first, then create a "prototype" object for the labels. Then iterate over the people and push an object to the output for each. To get the day label to use, take the index of the "people" being iterated over, and look it that index (plus 4) on the array of labels:

jQuery.ajax({
  url: "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv",
  type: 'get',
  dataType: 'text',
  success: function(data) {
    const lines = data.split('\n');
    const labelKeys = lines.shift().split(',');
    const output = [];
    for (const line of lines) {
      const cases = [];
      const items = line.split(',');
      const labelValues = items.slice(0, 4);
      const peopleArr = items.slice(4);
      const doc = {};
      for (let i = 0; i < 4; i++) {
        doc[labelKeys[i]] = labelValues[i];
      }
      peopleArr.forEach((people, i) => {
        const date = labelKeys[i + 4];
        cases.push({ date, people });
      });
      output.push({ ...doc, cases });
    }
    console.log(output.slice(0, 4));
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>



回答3:


If you're not sure if the data format will include key changes then you should not rely on knowing all of the keys (ie. maybe they add "quarantined: true" to the JSON response). Instead you can check to see if a key is a date value or not using isNaN( Date.parse(key) ).

The following code won't "miss" added key:value pairs.

$.ajax({
    url: "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv",
    success: function(csv) {
        const output = Papa.parse(csv, {
          header: true, // Convert rows to Objects using headers as properties
        });
        if (output.data) {
        const covidArray = [];
        output.data.forEach( function(item,index){
          let covid = new Object;
          covid.Cases = [];
          for(let key in item) {
            // Check if the key is a date or not
            if(isNaN(Date.parse(item[key]))){
              covid[key] = item[key];
            } else {
              covid.Cases.push( { "date" : key, "people" : item[key] } );
            }
          }
          covidArray.push(covid);
        });

        // The whole array reformatted
        console.log(covidArray);

        } else {
          console.log(output.errors);
        }
    },
    error: function(jqXHR, textStatus, errorThrow){
        console.log(textStatus);
    }
});



回答4:


You can postprocess the CSV data by putting anything that looks like a date into a dates array instead:

for (const row of output.data) {
  row.cases = []
  for (const [key, value] of Object.entries(row)) {
    if (key.match(/^\d+\/\d+\/\d+$/)) { // Is of format #/#/#
      delete row[key]
      row.cases.push({ date: key, people: Number(value) })
    }
  }
}

Afterwards, output.data will have the format you want.




回答5:


You can re-construct the object and use regex to check if the property name is a date format, and do the manipulation accordingly:

$.ajax({
  url: "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv",
  success: function(csv) {
    const output = Papa.parse(csv, {
      header: true, // Convert rows to Objects using headers as properties
    });
    if (output.data) {
      //console.log(output.data);
      output.data = output.data.slice(0, 3); // ONLY DO 3 entries here in the demo because it is a huge array
      let newData = [];
      output.data.forEach(place => {
        const newPlace = {};
        newPlace.cases = [];
        for (p in place) {
          if ((/^\d+\/\d+\/\d+$/).test(p)) {
            newPlace.cases.push({
              date: p, count: place[p]
            });
          } else {
            newPlace[p] = place[p];
          }
        }
        newData.push(newPlace);
      });
      console.log(newData);
    } else {
      console.log(output.errors);
    }
  },
  error: function(jqXHR, textStatus, errorThrow) {
    console.log(textStatus);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>


来源:https://stackoverflow.com/questions/60583604/how-to-split-and-create-single-objects-in-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!