Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty Array Being Returned as Header causing JSON to be Outputted in CSV #168

Open
4 of 5 tasks
hdwatts opened this issue Oct 20, 2020 · 8 comments
Open
4 of 5 tasks

Comments

@hdwatts
Copy link
Contributor

hdwatts commented Oct 20, 2020

Background Information

  • Module Version: 3.7.8
  • Node/Browser Version: 86.0.4240.80

The issue I'm reporting is with:

  • json2csv
  • csv2json

I have...

  • searched to see if an issue has already been reported.
  • verified that my JSON/CSV data is valid (using something like http://jsonlint.com or https://csvlint.io/).
  • tried upgrading to the latest version of json-2-csv (since the issue may already be fixed).

Expected Behavior

entities.id,entities.name,entities.siblings.entity.name,entities.siblings.relationship_set.relationships.relationship.name
4,Zeus,Exo,Senior
4,Zeus,Chrono,null

Actual Behavior

entities.id,entities.name,entities.siblings.entity.name,entities.siblings.relationship_set.relationships.relationship.name,entities.siblings.relationship_set.relationships
4,Zeus,Exo,Senior,"{""relationship"":{""name"":""Senior""}}"
4,Zeus,Chrono,null,

Data Sample

JSON:

{
  "entities":
    {
      "id": 4,
      "name": "Zeus",
      "siblings": [
        {
          "entity": {
            "name": "Exo",
          },
          "relationship_set": {
            "relationships": [
              {
                "relationship": {
                  "name": "Senior"
                },
              },
            ]
          }
        },
        {
          "entity": {
            "name": "Chrono"
          },
          "relationship_set": {
            "relationships": []
          }
        }
      ]
    }
}

Code Example

// Please include a simple example to replicate the issue
let converter = require('json-2-csv');
const obj1 = {
  "entities":
    {
      "id": 4,
      "name": "Zeus",
      "siblings": [
        {
          "entity": {
            "name": "Exo",
          },
          "relationship_set": {
            "relationships": [
              {
                "relationship": {
                  "name": "Senior"
                },
              },
            ]
          }
        },
        {
          "entity": {
            "name": "Chrono"
          },
          "relationship_set": {
            "relationships": []
          }
        }
      ]
    }
}

converter.json2csv(obj1, (err, csv) => {
    console.log(csv)
  }, { unwindArrays: true, expandArrayObjects: true })
@hdwatts
Copy link
Contributor Author

hdwatts commented Oct 20, 2020

To note, while messing around I found a way to get the expected output, but do not think it is the correct solution as it causes a test to fail. I solved it by updating deeks.generateDeepKeysList to return no key if there is an array to recur on but it is empty:

} else if (isArrayToRecurOn(data[currentKey]) && !data[currentKey].length) {
    return []
}

and then changing json-2-csv.utils, where we "push an empty string so the value is empty since there are no values" to instead push an empty array instead of an empty string:

path.setPath(cloned, fieldPath, []);

This is obviously not the right solution, however it brings about the expected output and may help you find the correct solution.

@hdwatts hdwatts changed the title Empty Array Being Returned as Header causing JSON output Empty Array Being Returned as Header causing JSON to be Outputted in CSV Oct 20, 2020
mrodrig added a commit that referenced this issue Jun 1, 2021
In order to convert the generated CSV back to the most accurate JSON
possible, the module must still insert `[]` for unwound empty array
values. However, there are some legitimate cases where users want to be
able to have the module ignore these values so that the generated CSV is
a bit more user-friendly, depending on the data being converted. This
new option allows users the ability to achieve this without impacting
existing use cases, as the user has opted to specify an option which may
impact the ability to convert the CSV back to JSON later on.

Fixes #168
@mrodrig mrodrig mentioned this issue Jun 1, 2021
2 tasks
mrodrig added a commit that referenced this issue Aug 9, 2021
In order to convert the generated CSV back to the most accurate JSON
possible, the module must still insert `[]` for unwound empty array
values. However, there are some legitimate cases where users want to be
able to have the module ignore these values so that the generated CSV is
a bit more user-friendly, depending on the data being converted. This
new option allows users the ability to achieve this without impacting
existing use cases, as the user has opted to specify an option which may
impact the ability to convert the CSV back to JSON later on.

Fixes #168
@loganpowell
Copy link

I'm having a similar issue, but with Objects. E.g.:

const test_json = [
    {
        a: 1,
        b: 2,
        c: {
            ca: 1,
            cb: 2,
        },
    },
    {
        a: 3,
        b: 4,
        c: {},
    },
]

json2csvAsync(test_json).then(console.log) //?

result:

a,b,c.ca,c.cb,c 
1,2,1,2,"{""ca"":1,""cb"":2}" 
3,4,undefined,undefined,{} 

I've looked through the docs to see how I might address this, but I've come up with nothing... Any tips?

🙏

@hdwatts
Copy link
Contributor Author

hdwatts commented Jan 20, 2022

@loganpowell I switched to https://github.com/kaue/jsonexport but I recommend using my fork from this PR: kaue/jsonexport#90

@loganpowell
Copy link

@hdwatts I tried that, but that leaves something to be desired as well. I'll follow up on that PR. with more info

@loganpowell
Copy link

I've used a work around to make sure a null set is present to keep the object structures similar and that is working for me atm... e.g.:

const test_json = [
    {
        a: 1,
        b: 2,
        c: {
            ca: 1,
            cb: 2,
        },
    },
    {
        a: 3,
        b: 4,
        c: {},
    },
]

const xfd = test_json.reduce((acc, cur) => {
    const null_set = { ca: null, cb: null }
    const { c, ...rest } = cur
    return acc.push({ ...((c.ca && { c }) || { c: null_set }), ...rest }), acc
}, [])
json2csvAsync(xfd).then(console.log) //?

result:

c.ca,c.cb,a,b 
1,2,1,2 
null,null,3,4 

@bmish
Copy link

bmish commented Feb 14, 2024

Hit the same issue as @loganpowell with an empty object yielding an unwanted JSON-filled column. Used a similar workaround.

@mrodrig
Copy link
Owner

mrodrig commented Feb 25, 2024

Thanks for bringing this up again. I'm trying to make some progress on these issues and will take another look to see if I can find a solution to resolve this since I agree that the behavior of printing a JSON object's representation isn't ideal.

@alinpr18
Copy link

alinpr18 commented Mar 3, 2024

It happens the same to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants