0

I have an JSON data coming back from an API, I want to convert it to an array, but having trouble getting the "timeline" category into the array,

Sample JSON:

[{
    "id": 100,
    "key1": 310797,
    "key2": 807874,
    "key3": 24283,
    "key4": 180900,
    "timeline": {
        "createDate": "2021-04-08T22:53:23Z",
        "lastChangeDate": "2021-04-27T12:03:57Z"
    }
},
{
    "id": 101,
    "key1": 310797,
    "key2": 807875,
    "key3": 24284,
    "key4": 180903,
    "timeline": {
        "createDate": "2021-04-04T22:53:23Z",
        "lastChangeDate": "2021-04-24T12:02:57Z"
    },
    {
        ...
    }
]

I am using the follow Javascript to try and parse this to an array

function convertToArray(json) {
    var headers = Object.keys(json[0]);
    var values = json.map(function(e) {
        return headers.map(function(f) {
            return e[f]
        })
    });
    values.unshift(headers);
    return values
}

This is returning:

[[id, key1, key2, key3, key4, timeline],
[100, 310797, 807874, 24283, 180900, ""],
[101, 310797, 807875, 24284, 180903, ""]]

However the Array I am trying to achieve is:

[[id, key1, key2, key3, key4, createDate, lastChangeDate],
[100, 310797, 807874, 24283, 180900, 2021-04-08T22:53:23Z, 2021-04-27T12:03:57Z],
[101, 310797, 807875, 24284, 180903, 2021-04-04T22:53:23Z, 2021-04-24T12:02:57Z]]

Any assistance with how I can map the "createDate" and "lastChangeDate" into the array would be truly appreciated

3 Answers 3

2

const arr = [
  {
    id: 100,
    key1: 310797,
    key2: 807874,
    key3: 24283,
    key4: 180900,
    timeline: {
      createDate: "2021-04-08T22:53:23Z",
      lastChangeDate: "2021-04-27T12:03:57Z",
    },
  },
  {
    id: 101,
    key1: 310797,
    key2: 807875,
    key3: 24284,
    key4: 180903,
    timeline: {
      createDate: "2021-04-04T22:53:23Z",
      lastChangeDate: "2021-04-24T12:02:57Z",
    },
  },
];

// Getting keys
let keys = [];
const obj = arr[0];
Object.entries(obj).forEach((entry) => {
  const [key, value] = entry;
  if (typeof value === "object") keys.push(...Object.keys(value));
  else keys.push(key);
});

// Getting values
const values = arr.map((obj) => {
  let temp = [];
  for (let key in obj) {
    if (typeof obj[key] === `object`) temp.push(...Object.values(obj[key]));
    else temp.push(obj[key]);
  }
  return temp;
});

result = [keys, ...values];

console.log(result);

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a solution that will collect keys and values from object structures recursively:

const arr = [
  {
    id: 100,
    key1: 310797,
    key2: 807874,
    key3: 24283,
    key4: 180900,
    timeline: {
      createDate: "2021-04-08T22:53:23Z",
      lastChangeDate: "2021-04-27T12:03:57Z",
      TZ: {TZname: "GMT", TZoffset: 0} // extended example: third level object
    },
  },
  {
    id: 101,
    key1: 310797,
    key2: 807875,
    key3: 24284,
    key4: 180903,
    timeline: {
      createDate: "2021-04-04T22:53:23Z",
      lastChangeDate: "2021-04-24T12:02:57Z",
    },
  },
];

// helper function getE : "get entry"
const getE=(j,ar=[],ge)=> // gets keys or values, dependent on `j`
  ge=c=>{Object.entries(c).forEach(e=>{
     if(typeof e[1] === "object") ge(e[1])
     else ar.push(e[j]);
  }); return ar};
  
 const res=arr.reduce((a,c,i)=>( !i && a.push(getE(0)(c)), a.push(getE(1)(c)), a),[] );

console.log(res)

The action happens within the function getE(): getE(j,ar=[],ge) sets a scope within which j (the quantity to be returned) and ar (an array for collection) are defined.

getE(j) has only one required argument: j, indicating the entry part to be returned: 0 for keys, 1 for values. It returns the function (ge(c)) that will recursively call itself on the intially given object c:

Within ge(c) the expression Object.entries(c).forEach() walks through all entries of c and will

  • either call itself with the current value part of the entry ge(e[1]),
    if (typeof e[1] === "object")is true

  • or will add the j-th part of the entry (e[j]) to the collection array ar

ge(c) returns the collection array ar.

1 Comment

Thank you for this answer and your clear description of how it works and where I went wrong. This is working perfectly
1

I put the timeline keys in a Set that can be used as a lookup when mapping row data and can be easily merged with he other keys for the headers

const timeKeys = new Set(Object.keys(data[0].timeline));

const headers  = Object.keys(data[0])
                   .filter(k => k!=='timeline')
                   .concat(...timeKeys);

const values = data.map(o => {
    return headers.map(k => {
      return timeKeys.has(k) ? o.timeline[k] : o[k];      
    });
});

const res = [headers , ...values];


console.log(res)
<script>
const data=[{id:100,key1:310797,key2:807874,key3:24283,key4:180900,timeline:{createDate:"2021-04-08T22:53:23Z",lastChangeDate:"2021-04-27T12:03:57Z"}},{id:101,key1:310797,key2:807875,key3:24284,key4:180903,timeline:{createDate:"2021-04-04T22:53:23Z",lastChangeDate:"2021-04-24T12:02:57Z"}}];
</script>

Comments

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.