Search code examples
javascriptregexparsingmatchcapturing-group

How to match all keys and values from a custom serialized object format?


I am trying to pick out all values from an object I have in string form. I have created the regular expression, but I am still having issues with not being able to remove the quotes and have hit a wall...

Here is the code I have with results I get compared to desired results:

const regex = /(?:"([^"]+)\")|([^=",{}.]+)/g
const string = 'obj{a="0",b="1",domain="a-ss.test.io:666",f="g",range="3.594e-04...4.084e-04"}'

const matches = string.match(regex)
console.log(matches)

Here is the resulting array:

[
    "obj",
    "a",
    "\"0\"",
    "b",
    "\"1\"",
    "domain",
    "\"a-ss.test.io:666\"",
    "f",
    "\"g\"",
    "range",
    "\"3.594e-04...4.084e-04\""
]

Though the desired result I would like is:

[
    "obj",
    "a",
    "0",
    "b",
    "1",
    "domain",
    "a-ss.test.io:666",
    "f",
    "g",
    "range",
    "3.594e-04...4.084e-04"
]

Does anyone know how to also remove the quotes from each array value that is returned?


Solution

  • You need to get whole match values in the result since String#match with a regular expression containing the /g flag loses all captures. See that String#match returns:

    An Array whose contents depend on the presence or absence of the global (g) flag, or null if no matches are found.

    • If the g flag is used, all results matching the complete regular expression will be returned, but capturing groups are not included.
    • If the g flag is not used, only the first complete match and its related capturing groups are returned. In this case, match() will return the same result as RegExp.prototype.exec() (an array with some extra properties).

    You want to get Group 1 or Group 2 values, so ask the engine to return just them:

    const regex = /"([^"]+)"|([^=",{}.]+)/g
    const string = 'obj{a="0",b="1",domain="a-ss.test.io:666",f="g",range="3.594e-04...4.084e-04"}'
    
    const matches = Array.from(string.matchAll(regex), x => x[1] || x[2])
    console.log(matches)