0

I have an issue I've not been able to solve, basically I want to transform this:

{
    "seamark:name": "Z-2",
    "seamark:type": "buoy_lateral",
    "seamark:light:range": "5",
    "seamark:light:colour": "red",
    "seamark:light:character": "Q",
    "seamark:radar_reflector": "yes",
    "seamark:buoy_lateral:shape": "can",
    "seamark:buoy_lateral:colour": "red",
    "seamark:buoy_lateral:system": "iala-a",
    "seamark:buoy_lateral:category": "port"
}

into this:

{
    seamark: {
        name: "Z-2",
        type: "buoy_lateral",
        light: {
            range: "5",
            colour: "red",
            reflector: "yes"
        },
        buoy_lateral: {
            shape: "can",
            colour: "red",
            system: "iala-a",
            category: "port
        }
    }
}

For now I've only achieved to get an array containing 10 objects with every time the path to the value (for example {seamark: {name: "Z-2"}}) using the code shown in the following link: codepen

Would anyone have an idea on how to group the properties deeply once I have the result shown in the codepen? Or maybe even another idea? thanks in advance

3 Answers 3

2

You are trying to unflat an object.

You can use flat npm (https://www.npmjs.com/package/flat)

const { unflatten } = require('flat');

const unflat = unflatten({
    "seamark:name": "Z-2",
    "seamark:type": "buoy_lateral",
    "seamark:light:range": "5",
    "seamark:light:colour": "red",
    "seamark:light:character": "Q",
    "seamark:radar_reflector": "yes",
    "seamark:buoy_lateral:shape": "can",
    "seamark:buoy_lateral:colour": "red",
    "seamark:buoy_lateral:system": "iala-a",
    "seamark:buoy_lateral:category": "port"
}, { delimiter: ":" }); // notice delimiter : default is "."

console.log(unflat);

Output:

{
    seamark: {
        name: 'Z-2',
        type: 'buoy_lateral',
        light: { range: '5', colour: 'red', character: 'Q' },
        radar_reflector: 'yes',
        buoy_lateral:
        {
            shape: 'can',
            colour: 'red',
            system: 'iala-a',
            category: 'port'
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Well that's exactly what I needed ! Didn't know the library, thanks :)
2

For setting a value, you could split the path and reduce the path by walking the given object. If no object exist, create a new property with the name. Later assign the value.

function setValue(object, path, value) {
    var last = path.pop();

    path.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
}

var data = { "seamark:name": "Z-2", "seamark:type": "buoy_lateral", "seamark:light:range": "5", "seamark:light:colour": "red", "seamark:light:character": "Q", "seamark:radar_reflector": "yes", "seamark:buoy_lateral:shape": "can", "seamark:buoy_lateral:colour": "red", "seamark:buoy_lateral:system": "iala-a", "seamark:buoy_lateral:category": "port" };

Object
    .keys(data)
    .forEach(k => {
        var keys = k.split(':');
        if (keys.length === 1) return;
        setValue(data, k.split(':'), data[k]);
        delete data[k];
    });

console.log(data);

1 Comment

Thanks for your answer, I like the fact it is concise, but I'm not a fan of changing the value of an object in another function than the one it was instantiated :/ I like the use of the library more since it is even more concise to just use a function, but thanks for your time !
1

You can also use "for..of" and "Array.reduce" like below

var obj = {
    "seamark:name": "Z-2",
    "seamark:type": "buoy_lateral",
    "seamark:light:range": "5",
    "seamark:light:colour": "red",
    "seamark:light:character": "Q",
    "seamark:radar_reflector": "yes",
    "seamark:buoy_lateral:shape": "can",
    "seamark:buoy_lateral:colour": "red",
    "seamark:buoy_lateral:system": "iala-a",
    "seamark:buoy_lateral:category": "port"
}


let newObj = {}
for(let [key, val] of Object.entries(obj)) {
  let keys = key.split(':')
  
  keys.reduce((o, d, i) => (
       i == keys.length - 1 
         ? (o[d] = val) 
         : (o[d] = o[d] || {})
       , o[d])
    , newObj)
}

console.log(newObj)

Comments

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.