Search code examples
pythonnode.jsjsoncsvdata-conversion

How can I convert CSV to JSON with data type in python or node.js?


I wanna convert CSV to JSON correct data type

csv file 2nd row is data type. data has over 300 properties example data:

Name DMG HP Human
string number number boolean
knight 100 500 true
archer 50 200 true
dog - - -

if string empty return null

if number empty return 0

if boolean empty return false

my node.js code:

const fs = require('fs')
const papa = require("papaparse")

const results = [];

const options = { header: true, dynamicTyping: true };

fs.createReadStream("characters.csv")
    .pipe(papa.parse(papa.NODE_STREAM_INPUT, options))
    .on("data", (data) => {
        results.push(data);
    }).on("end", () => {
        console.log(results)
    })

output I expecting:

[
    {
        "Name": "knight",
        "DMG": 100,
        "HP": 500,
        "Human": true,
    },
    {
        "Name": "archer",
        "DMG": 50,
        "HP": 200,
        "Human": true,
    },
    {
        "Name": "dog",
        "DMG": 0,
        "HP": 0,
        "Human": false,
    },
]

Solution

  • Options options..

    in this approach I cached the headerTypes and made a small helper function to return the intended type

    define the vars let i = 0, headerTypes = {};

    replace your on.data code with this

    .on("data", (data) => {
        if(i > 0){
           for(let prop in data){
                if(data.hasOwnProperty(prop)){
                    const value = data[prop];
                    data[prop] = typecast(headerTypes[prop], value);
                }
            }
        }else{
            //save types from row 0
            headerTypes = data;
        }
        i++;
    })
    

    add this helper function

    function typecast(type = '', value){
        switch(type){
          case "number":
            return +value || 0; //unary for int or float
          case "boolean":
            return value === !0; //typecast to Boolean will let any filled string like '-' be true, do this instead.
          case "string":
          default:
            return String(value);
        }
    }