19

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!

1
  • 1
    You must have some problems with double stringification. If I run your reduce against the initial string from the provided data, with minor modifications, it looks exactly as you expect it: jsfiddle.net/pxjycsLa. Check out the fiddle by opening the console. Commented Jul 9, 2017 at 19:58

3 Answers 3

16

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);

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

8 Comments

Thats almost exactly what OP is doing and it is working fine, yeah. But how is this an answer?
Code modifications and explanations?
There is clearly another problem in the question. If you apply OP's code as is in the original data string you do not get the same result as OP says he is getting. I think the answer lies in finding whats wrong with the initial string.
@FreemanLambda Sure you do. Make rawNoteData equal to the example string and you'll get what the OP referred to as a "crazy-looking object".
@J. Titus yep!! That seems to work! lol did exactly that after thinking about it for 2 seconds.
|
3

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

Comments

1

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));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.