0

I have a string which contains multiple properties and sub-properties, which I would like to convert to a JSON object. The string I currently have is of this format:

"{"menuId":"1","menuItemDetails.itemDetailsId":"4","menuItemDetails.itemType.itemTypeId":"4","accessGroups":"","menuItemDetails.name":"","menuItemDetails.route":"","menuItemDetails.displayRule":"","menuItemDetails.continueMode":"","menuItemDetails.isSilent":"0","menuItemDetails.message.messageId":"26","menuItemDetails.title.messageId":"","menuItemDetails.defaultMessage.messageId":"","menuItemDetails.onSelect.messageId":"","menuItemDetails.action.actionId":"2","menuItemDetails.action.actionTypeId":"2","menuItemDetails.action.name":"GenerateViewMembersAction","menuItemDetails.action.fullyQualifiedName":"test.actions.sharedplans.GenerateViewMembersAction","menuItemDetails.action.plugin.pluginId":"1"}"

If I do a normal JSON.parse, I get an object like the following:

accessGroups
:
""
menuId
:
"1"
menuItemDetails.action.actionId
:
"2"
menuItemDetails.action.actionTypeId
:
"2"
menuItemDetails.action.fullyQualifiedName
:
"test.GenerateViewMembersAction"
menuItemDetails.action.name
:
"GenerateViewMembersAction"

I would like to group by propreties name, so I get the following:

{
 menuId: 1
,menuItemDetails: {
  action: {
     actionId: 1
    ,actionTypeId: 2
    ...
   }
,name: "GenerateView..."
 }
}

Anyone can help me figure this out?

EDIT: To put things more into perspective, the case I have is a list of HTML elements, each having a name and a value, from which I want to build the JSON object. That does give me control over the JSON string, or allows me to create a JSON object directly if needed.

Waddah Ajaj
  • 121
  • 1
  • 10
  • Your input is in JSON format so `JSON.parse` is going to read every key-value pair delimited by commas and assign those properties and values to an object. You have properties like `menuItemDetails.itemDetailsId`, which will be the literal name of the property, not create an inner `menuItemDetails` object. JSON supports nested objects, can't you rewrite your input? – glhrmv May 10 '17 at 15:31
  • If changing whatever builds the string is an option, that's the way to go here, otherwise, you're looking at this question, which seems similar:http://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference – JoeTortuga May 10 '17 at 15:59

1 Answers1

3

You cannot use the JSON parser as is, since it simply treats "menuItemDetails.itemDetailsId" as a monolithic identifier. After all, how should it know that this actually depicts a nested object.

You either have to write your own parser that reads the string and creates the object structure taking your special circumstances into account. This however is a quite cumbersome task (if you want to do it properly).

I would go with a two-step approach. First use the built-in JSON parser to create a regular object. Then, iterate over your object properties and simply split all the properties containing a . and combine them into new nested objects. You can use regular code for copying objects (which is not trivial as well) and then add your special rule to split the keys containing a . accordingly.

Splitting an object path could be done like following (this however does not account for duplicate paths!):

obj = {"test.foo.bar.baz":"value","one.two":"anothervalue"};
var out = {};

Object.entries(obj).forEach(
   (e)=> e[0].split(".")
             .reduceRight(function(acc, val,i) {
                 return (i==0) ? out[val] = acc : {[val] : acc};
             }, e[1])
);

console.log(out);

If you have control over it, the easiest thing is prabobly to correct the input string in the first place.

Community
  • 1
  • 1
Christoph
  • 50,121
  • 21
  • 99
  • 128