Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert an array to json object by javascript

I am stuck to solve this problem. Convert an array below

var input = [
    'animal/mammal/dog',
    'animal/mammal/cat/tiger',
    'animal/mammal/cat/lion',
    'animal/mammal/elephant',
    'animal/reptile',
    'plant/sunflower'
]

to json Object

var expectedResult = {
 "animal": {
  "mammal": {
   "dog": true,
   "cat": {
    "tiger": true,
    "lion": true
   },
   "elephant": true
  },
  "reptile": true
 },
 "plant": {
  "sunflower": true
 }
}

Which data structure and algorithm can I apply for it? Thanks

like image 917
Le Duc Anh Avatar asked May 24 '20 14:05

Le Duc Anh


People also ask

How do I convert an array of objects to JSON?

You convert the whole array to JSON as one object by calling JSON. stringify() on the array, which results in a single JSON string. To convert back to an array from JSON, you'd call JSON. parse() on the string, leaving you with the original array.

Can we convert array to object in JavaScript?

To convert an array to an object, use the reduce() method to iterate over the array, passing it an object as the initial value. On each iteration, assign a new key-value pair to the accumulated object and return the result. Copied!

How do you Stringify an array in JavaScript?

Stringify a JavaScript Array Use the JavaScript function JSON. stringify() to convert it into a string. const myJSON = JSON. stringify(arr);

How do you parse an array of JSON objects?

Parsing JSON Data in JavaScript In JavaScript, you can easily parse JSON data received from the web server using the JSON. parse() method. This method parses a JSON string and constructs the JavaScript value or object described by the string. If the given string is not valid JSON, you will get a syntax error.


2 Answers

You need to first split each element to convert to array

using reverse reduce method you can convert them to object.

And your last step is merge this objects.

Lodash.js merge method is an one way to merge them.

var input = ['animal/mammal/dog','animal/mammal/cat/tiger','animal/mammal/cat/lion', 'animal/mammal/elephant','animal/reptile', 'plant/sunflower']
var finalbyLodash={}
input.forEach(x=>{
  const keys = x.split("/");
  const result = keys.reverse().reduce((res, key) => ({[key]: res}), true);
  finalbyLodash = _.merge({}, finalbyLodash, result);
});
console.log(finalbyLodash);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
like image 183
mr. pc_coder Avatar answered Nov 02 '22 15:11

mr. pc_coder


To make the process more understandable, break the problem down into pieces.

The first step is convert each string into something we can use, converting this:

"animal/mammal/dog"

into this:

[ "animal", "mammal", "dog" ]

That's an array of property names needed to build the final object.

Two functions will accomplish this for you, String.prototype.split() to split the string into an array, and Array.prototype.map() to transform each of the array elements:

let splitIntoNames = input.map(str => str.split('/'));

The intermediate result is this:

[
  [ "animal", "mammal", "dog" ],
  [ "animal", "mammal", "cat", "tiger" ],
  [ "animal", "mammal", "cat", "lion" ],
  [ "animal", "mammal", "elephant" ],
  [ "animal", "reptile" ],
  [ "plant", "sunflower" ]
]

Next step is to iterate over each array, using Array.prototype.forEach() to add properties to the object. You could add properties to the object with a for loop, but let's do that with a recursive function addName():

function addName(element, list, index) {
  if (index >= list.length) {
    return;
  }
  let name = list[index];
  let isEndOfList = index === list.length - 1;

  element[name] = element[name] || (isEndOfList ? true : {});

  addName(element[name], list, index + 1);
}

let result = {};
splitIntoNames.forEach((list) => {
  addName(result, list, 0);
});

The result:

result: {
  "animal": {
    "mammal": {
      "dog": true,
      "cat": {
        "tiger": true,
        "lion": true
      },
      "elephant": true
    },
    "reptile": true
  },
  "plant": {
    "sunflower": true
  }
}

const input = [
  "animal/mammal/dog",
  "animal/mammal/cat/tiger",
  "animal/mammal/cat/lion",
  "animal/mammal/elephant",
  "animal/reptile",
  "plant/sunflower",
];

let splitIntoNames = input.map((str) => str.split("/"));
console.log("splitIntoNames:", JSON.stringify(splitIntoNames, null, 2));

function addName(element, list, index) {
  if (index >= list.length) {
    return;
  }
  let name = list[index];
  let isEndOfList = index === list.length - 1;

  element[name] = element[name] || (isEndOfList ? true : {});

  addName(element[name], list, index + 1);
}

let result = {};
splitIntoNames.forEach((list) => {
  addName(result, list, 0);
});
console.log("result:", JSON.stringify(result, null, 2));
like image 39
terrymorse Avatar answered Nov 02 '22 14:11

terrymorse