0

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,
    },
]
4
  • 1
    Does this answer your question? How to convert csv to json in python? Commented Nov 16, 2022 at 5:41
  • it's not have 2nd row data type Commented Nov 16, 2022 at 5:45
  • Use the package CSVtoJSON Commented Nov 16, 2022 at 6:36
  • updated answer to support 300 or 300,000 columns. this should do the trick. Also updated the typecast function to send 0 if the unary produces NaN Commented Nov 16, 2022 at 6:41

2 Answers 2

1

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);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

now instead of writing these properties out like I did, you can loop through the properties instead
this should work for multiple rows without having to define them. just add types to typecast as needed.
ok if it's work I'll be back and accept your answer thanks
0

Try overriding the properties in the on.data event like so

let i = 0; //define this outside, its only to skip that first row with headers.
if(i > 0){ //skipping first row
    data.DMG = parseInt(data.DMG) || 0; //an int or 0
    data.HP = parseInt(data.HP) || 0; //an int or 0
    data.Human = data.Human === !0; //!0 = not false, will match true string or bool
    results.push(data);
}
i++;//iterate

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

const results = [];

const options = { header: true, dynamicTyping: true };
let i = 0;
fs.createReadStream("characters.csv")
    .pipe(papa.parse(papa.NODE_STREAM_INPUT, options))
    .on("data", (data) => {
        //add this here
        if(i > 0){
            data.DMG = parseInt(data.DMG) || 0; //an int or 0
            data.HP = parseInt(data.HP) || 0; //an int or 0
            data.Human = data.Human === !0; //!0 = not false, will match true string or bool
            results.push(data);
        }
        i++;
        //end add this here
    }).on("end", () => {
    console.log(results)
})

3 Comments

thanks. but my data have over 300 properties it's could be difficult to write whole 300 props. do you have another way?
see 2nd answer, I got bored :)
any idea to directly check type in 2nd row?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.