1

I have the following string:

desc: random text string, sender: James, se-status: red, action: runs, target: John, ta-status: blue, status-apply: red, lore: lore ipsum dolor sit amet

The string is kind of formatted like JSON, just without all the brackets and line breaks and stuff that make it actually useful.

This string always has the categories desc, sender, se-status, action, target, ta-status, status-apply, and lore. They always appear in that order, but may not always be present, and can carry any string.

The issue is that they can carry literally any string at all - for example, sender could carry the string "se-status:" and confuse things. But, that's really unlikely to happen so it shouldn't be an issue really.

It's much more likely that it could contain a comma, which is really useful for breaking methods of extracting the data.

Anyway.

Say I have the aforementioned string in a variable string. How would I make it so that string.sender === James, and the same for all other categories in the original string?

3
  • 2
    Can the string content contain ,, or is it a safe delimiter? Commented May 16, 2016 at 22:57
  • Why not just make it real JSON? Where does this text come from? Commented May 16, 2016 at 23:15
  • The string can contain any character. It's taken from Google Sheets and arrives to me in this format. Commented May 16, 2016 at 23:36

3 Answers 3

1

I guess a regex should do the job. Here is the explanation

(desc|sender|se-status|action|target|ta-status|status-apply|lore)(?=:):\s?([^:]+)(?=(,\ssender|,\sse-status|,\saction|,\starget|,\sta-status|,\sstatus-apply|,\slore|$))

Regular expression visualization

Debuggex Demo

You can check the accompanying JS code and it's result below;

var   r = /(desc|sender|se-status|action|target|ta-status|status-apply|lore)(?=:):\s?([^:]+)(?=(,\ssender|,\sse-status|,\saction|,\starget|,\sta-status|,\sstatus-apply|,\slore|$))/g,
    str = "desc: random text string, sender: James, se-status: red, action: runs, target: John, ta-status: blue, status-apply: red, lore: lore ipsum dolor sit amet",
dataObj = {},
  match = [];
while(match[match.length] = r.exec(str));
match.length--;
dataObj = match.reduce((p,c) => (p[c[1]] = c[2],p),{});

document.write("<pre>" + JSON.stringify(dataObj,null,2) + "</pre>");

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

Comments

0

Here is one way to do it:

var str = "desc: random text string, sender: James, se-status: red, action: runs, target: John, ta-status: blue, status-apply: red, lore: lore ipsum dolor sit amet";

var obj = {};
str.split(',').forEach(function(line) {
     var l = line.split(':');   
   obj[l[0].trim()] = (l[1].trim());   
});

console.log(obj);
console.log(JSON.stringify(obj));

as a function:

function myStrToObj(str) {
  var obj = {};
  str.split(',').forEach(function(line) {
     var l = line.split(':');   
     obj[l[0].trim()] = (l[1].trim());   
  });
    return obj;
}

Edit after explanation from OP

a better parser:

function myStrToObj(str) {
    var lastColon = lastComma = -1;
    var key = value = '';
    var obj = {};
    for(var i = 0; i < str.length; i++) {
        if (str[i] == ':') {
            if (lastColon > 0) {
                value = str.substring(lastColon + 1, lastComma).trim();
                obj[key] = value;
                key = str.substring(lastComma + 1, i).trim();
            } else 
                key = str.substring(0, i).trim();
            lastColon = i;
        };

        if (str[i] == ',') 
             lastComma = i;
    };
    value = str.substring(lastColon + 1, str.length).trim();
    obj[key] = value;        
    return obj;
} 

var str = "desc: random text string, sender: James, se-status: red, problem-field: I'm a problem field, I'm a problem field,  action: runs, target: John, ta-status: blue, status-apply: red, lore: lore ipsum dolor sit amet";
var obj = myStrToObj(str);

console.log(obj);

I put a JSFiddle with it here: https://jsfiddle.net/gnLk6fdd/14/

Edit based on Redu's answer

As I saw Redu's answer I thought it would be much better to create a regex to this. But the problem with his answer is that the field names have to be fixed. I tried to create a regex with capturing groups instead of my answer . My idea was to capture the group, repeat and then go back to last comma or beggining. But my knowlege of regex doesn't get that far.

So I created a question to see if someone can create a regex to this:

How can I create a regex to parse this string

Based on the question I linked above and the corresponding answer by Thomas Ayoub, I saw that if you get Redu's answer and just replace regex by:

var r = /([\w-]+):([\w,\s']+)(?:,|$)/g; 

You can check string without fixed fields.And it's a much better solution than my for loop.

Demo: https://jsfiddle.net/yao97m4s/7/

16 Comments

This works perfectly, assuming none of the values contain the comma character. Would there be a way to go about solving that? Thank you very much for your time thusly.
Yes, but you would have to make a more complex parser, that analyse the string char by char looking for : character and then return back to the last comma found to delimit the field. Do you have the option of changing the delimit character from comma to, say, pipe (|) ?
Sadly not - I'm accessing this data through a Google Sheets URL. The data it provides me with is actually JSON, but the bit that I want to look at isn't... here's the URL spreadsheets.google.com/feeds/list/… - it may be beneficial to paste this into a beautifier. As you can see, I can change the values themselves, but not the delimiter
Additionally here's the original sheet docs.google.com/spreadsheets/d/… - I could rename the headers so they're all of equal length, that might make the process easier.
but this is already a json response... you just load it on a object directly... like var json = output and you're done :)
|
0

Tricky question but here is one way to turn that string into an object:

Working Example

var s = " desc: random text string, sender: James, se-status: red, action: runs, target: John, ta-status: blue, status-apply: red, lore: lore ipsum dolor sit amet";

var tuples = s.split(',').map(function(a){
  return a.split(':');
}).map(function(b) {
    var obj = {};
    obj[b[0].substring(1)] = b[1].substring(1);
    return obj;
});

var obj = Object.assign.apply({}, tuples);
  • split by ',' to get pairs, then split each pair by ':' to get an array of tuples
  • map the array of tuples to make objects
  • assign all those objects to a new new empty object

now obj.sender is equal to 'James'

1 Comment

This also works perfectly, assuming none of the strings contain a comma. I don't suppose you'd know how to go about averting that error? Thank you very much for your time so far.

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.