Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem dealing with a space when moving JSON to Python

I am high school math teacher who is teaching myself programming. My apologies in advance if I don't phrase some of this correctly.

I am collecting CSV data from the user and trying to move it to a SQLite database via Python.

Everything works fine unless one of the values has a space in it.

For example, here is part of my JavaScript object:

Firstname: "Bruce"
Grade: ""
Lastname: "Wayne Jr"
Nickname: ""

Here is the corresponding piece after applying JSON.stringify:

{"Firstname":"Bruce","Lastname":"Wayne Jr","Nickname":"","Grade":""}

This is then passed to Python via a form. In Python, I use:

data = request.form.get("data")
print(data)
data2 = json.loads(data)
print(data2)

I get a bunch of error messages, ending with: json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 250 (char 249) and the log of the first print gives:

[{"Firstname":"Jason","Lastname":"Bourne","Nickname":"","Grade":"10"},
 {"Firstname":"Steve","Lastname":"McGarret","Nickname":"5-0","Grade":""},
 {"Firstname":"Danny","Lastname":"Williams","Nickname":"Dano","Grade":"12"},
 {"Firstname":"Bruce","Lastname":"Wayne

So it seems to break on the space in "Wayne Jr".

I used what I learned here to build the basics:
https://bl.ocks.org/HarryStevens/0ce529b9b5e4ea17f8db25324423818f

I believe this JavaScript function is parsing the user data:

function changeDataFromField(cb){
   var arr = [];
   $('#enter-data-field').val().replace( /\n/g, "^^^xyz" ).split( "^^^xyz" ).forEach(function(d){
     arr.push(d.replace( /\t/g, "^^^xyz" ).split( "^^^xyz" ))
   });
   cb(csvToJson(arr));
 }

Updates based on comments:
I am using a POST request. No AJAX.

There are actually 2 inputs for the user. A text box where they can paste CSV data and a file upload option. Here is some more of the JavaScript.

// Use the HTML5 File API to read the CSV
  function changeDataFromUpload(evt, cb){
    if (!browserSupportFileUpload()) {
      console.error("The File APIs are not fully supported in this browser!");
    } else {
      var data = null;
      var file = evt.target.files[0];
      var fileName = file.name;
      $("#filename").html(fileName);

      if (file !== "") {
        var reader = new FileReader();

        reader.onload = function(event) {
          var csvData = event.target.result;
          var parsed = Papa.parse(csvData);
          cb(csvToJson(parsed.data));
        };
        reader.onerror = function() {
          console.error("Unable to read " + file.fileName);
        };
      }

      reader.readAsText(file);
      $("#update-data-from-file")[0].value = "";
    }
  }

  // Method that checks that the browser supports the HTML5 File API
  function browserSupportFileUpload() {
    var isCompatible = false;
    if (window.File && window.FileReader && window.FileList && window.Blob) {
      isCompatible = true;
    }
    return isCompatible;
  }

  // Parse the CSV input into JSON
  function csvToJson(data) {
    var cols = ["Firstname","Lastname","Nickname","Grade"];
    var out = [];
    for (var i = 0; i < data.length; i++){
      var obj = {};
      var row = data[i];
      cols.forEach(function(col, index){
        if (row[index]) {
          obj[col] = row[index];
        }
        else {
          obj[col] = "";
        }
      });
      out.push(obj);
    }
    return out;
  }

  //  Produces table for user to check appearance of data and button to complete upload
  function makeTable(data) {
    console.log(data);
    send_data = JSON.stringify(data);
    console.log(send_data);
      var table_data = '<table style="table-layout: fixed; width: 100%" class="table table-striped">';
      table_data += '<th>First name</th><th>Last name</th><th>Nickname</th><th>Grade</th>'
      for(var count = 0; count < data.length; count++) {
        table_data += '<tr>';
            table_data += '<td>'+data[count]['Firstname']+'</td>';
            table_data += '<td>'+data[count]['Lastname']+'</td>';
            table_data += '<td>'+data[count]['Nickname']+'</td>';
            table_data += '<td>'+data[count]['Grade']+'</td>';
        table_data += '</tr>';
        }
      table_data += '</table>';
      table_data += '<p><form action="/uploaded" method="post">';
      table_data += 'Does the data look OK? If so, click to upload.  ';
      table_data += '<button class="btn btn-primary" type="submit">Upload</button><p>';
      table_data += '<input type="hidden" id="data" name="data" value='+send_data+'>';
      table_data += '<input type="hidden" name="class_id" value="{{ class_id }}">';
      table_data += '</form>';
      table_data += 'Otherwise, fix the file and reload.';
      document.getElementById("result_table").innerHTML = table_data;
  }
  </script>
like image 849
MathGuy297 Avatar asked Nov 06 '22 23:11

MathGuy297


1 Answers

The JavaScript can be made a lot simpler. If you do the following instead, do you have any problems with the JSON getting cut off?

document.getElementById('update-data-from-file').addEventListener('change', function(evt){
  var file = evt.target.files[0];
  document.getElementById('filename').innerText = file.name

  if (file === "")
    return;

  Papa.parse(file, {
    header: true,
    skipEmptyLines: true,
    complete: function(results) {
      json = results.data
      console.log(json)
      // Do stuff with the json here
    }
  });

  document.getElementById('update-data-from-file').value = ''
})
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.0.2/papaparse.min.js"></script>
  </head>
  <body>

    <label>
      Upload CSV
      <input type="file" name="File Upload" id="update-data-from-file" accept=".csv" />
    </label>
    <div id="filename">No file chosen</div>
    
  </body>
</html>
like image 125
hostingutilities.com Avatar answered Nov 11 '22 06:11

hostingutilities.com