JoethaCoder
JoethaCoder

Reputation: 506

JavaScript Split String into Object with Properties

I am having an issue where an API is giving me a long string that contains multiple items that need to be broken out into an object. Here is an example of the string:

"Child 1 First Name: Ali\nChild 1 Gender: Female\nChild 1 Hair Color: Blonde\nChild 1 Hair Style: Wavy\nChild 1 Skin Tone: Tan\nChild 2 First Name: Morgan \nChild 2 Gender: Female\nChild 2 Hair Color: Brown\nChild 2 Hair Style: Ponytail\nChild 2 Skin Tone: Light\nRelationship 1 to 2: Brother\nRelationship 2 to 1: Brother\n"

It is using \n to break everything into multiple lines. The string is one property of a larger object being sent by the API. For some reason when I try and use the .split method on it like (full code below) I need to use JSON.stringify in order to get my function to even begin to work.

Here is my full code:

let rawNoteData = order.customer.note;
let data = JSON.stringify(rawNoteData);

let foo = data.split("\n").reduce(function(obj, str, index) {
  let strParts = str.split(":");
  obj[strParts[0].replace(/\s+/g, '')] = strParts[1];
  return obj;
}, {});

console.log(foo);

This is creating really crazy looking objects that look like this:

{'"Child1FirstName': ' Arabelle\\nChild 1 Gender' }

I think my function is only working for the first instance. I am a little uncertain on how to fix this and clean up all of the crazy quotes etc going on.

My goal is to split the string into an object like so:

mongoExDoc: {
  child1FirstName: "Ali",
  child1Gender: "Female",
  child1HairColor: "Blonde",
  child1HairStyle: "Wavy",
  child1SkinTone: "Tan",
  child2FirstName: "Morgan",
  child2Gender: "Female",
  child2HairColor: "Brown",
  child2HairStyle: "Ponytail",
  child2SkinTone: "Light",
  relationship1To2: "Brother",
  relationship2To1: "Brother"
}

From there I will be combining its properties with another object being inserted into MongoDB.

Any help is GREATLY appreciated!

Upvotes: 19

Views: 31854

Answers (3)

Mike
Mike

Reputation: 151

Something like this?

let data = 'Child 1 First Name: Ali\nChild 1 Gender: Female\nChild 1 Hair Color: Blonde\nChild 1 Hair Style: Wavy\nChild 1 Skin Tone: Tan\nChild 2 First Name: Morgan \nChild 2 Gender: Female\nChild 2 Hair Color: Brown\nChild 2 Hair Style: Ponytail\nChild 2 Skin Tone: Light\nRelationship 1 to 2: Brother\nRelationship 2 to 1: Brother\n';
let target = {};

data.split('\n').forEach((pair) => {
  if(pair !== '') {
    let splitpair = pair.split(': ');
    let key = splitpair[0].charAt(0).toLowerCase() + splitpair[0].slice(1).split(' ').join('');
    target[key] = splitpair[1];
  }
});

console.dir(target);

produces an object like what you're asking for

Upvotes: 3

Ori Drori
Ori Drori

Reputation: 191976

I can think of 2 methods to convert the string to an object:

  1. Create a JSON string, and parsing using JSON#parse.

const str = "Child 1 First Name: Ali\nChild 1 Gender: Female\nChild 1 Hair Color: Blonde\nChild 1 Hair Style: Wavy\nChild 1 Skin Tone: Tan\nChild 2 First Name: Morgan \nChild 2 Gender: Female\nChild 2 Hair Color: Brown\nChild 2 Hair Style: Ponytail\nChild 2 Skin Tone: Light\nRelationship 1 to 2: Brother\nRelationship 2 to 1: Brother\n";

const toObject = (str) => {
  const json = str.replace(/([^\:]+)\:([^\n]+)\n/g, (_, p1, p2) => {
    return `"${p1.replace(/\s+/g, '')}":"${p2.trim()}",`;
  });

  return JSON.parse(`{${json.slice(0, -1)}}`);
};


console.log(toObject(str));

Or

  1. Match parts of the string and iterate to create an object:

const str = "Child 1 First Name: Ali\nChild 1 Gender: Female\nChild 1 Hair Color: Blonde\nChild 1 Hair Style: Wavy\nChild 1 Skin Tone: Tan\nChild 2 First Name: Morgan \nChild 2 Gender: Female\nChild 2 Hair Color: Brown\nChild 2 Hair Style: Ponytail\nChild 2 Skin Tone: Light\nRelationship 1 to 2: Brother\nRelationship 2 to 1: Brother\n";

const toObject = (str) => {
  const arr = str.match(/[^\:\n]+/g);
  const obj = {};
  
  for(let i = 0; i < arr.length; i += 2) {
    obj[arr[i].replace(/\s+/g, '')] = arr[i + 1].trim();
  }
  
  return obj;
};


console.log(toObject(str));

Upvotes: 1

J. Titus
J. Titus

Reputation: 9690

If order.customer.note is your example string, then this should work:

let data = "Child 1 First Name: Ali\nChild 1 Gender: Female\nChild 1 Hair Color: Blonde\nChild 1 Hair Style: Wavy\nChild 1 Skin Tone: Tan\nChild 2 First Name: Morgan \nChild 2 Gender: Female\nChild 2 Hair Color: Brown\nChild 2 Hair Style: Ponytail\nChild 2 Skin Tone: Light\nRelationship 1 to 2: Brother\nRelationship 2 to 1: Brother\n";
//let data = JSON.stringify(rawNoteData);  <-- Don't do this. order.customer.note is not an object.

let foo = data.split("\n").reduce(function(obj, str, index) {
  let strParts = str.split(":");
  if (strParts[0] && strParts[1]) { //<-- Make sure the key & value are not undefined
    obj[strParts[0].replace(/\s+/g, '')] = strParts[1].trim(); //<-- Get rid of extra spaces at beginning of value strings
  }
  return obj;
}, {});

console.log(foo);

Upvotes: 16

Related Questions