ini icon indicating copy to clipboard operation
ini copied to clipboard

dots aren't decoded in deeply nested sections

Open rlidwka opened this issue 10 years ago • 8 comments

> require('ini').decode('[x\\.y\\.z.a\\.b\\.c]\nfoo=bar')
{ 'x\\.y\\.z': { 'a.b.c': { foo: 'bar' } } }

rlidwka avatar Feb 11 '14 17:02 rlidwka

+1

Example №1

[test]
lvl1.value = value1
lvl1.lvl2.value1 = 1

will return

{ 'lvl1.value': 'value1', 'lvl1.lvl2.value1': '1' }

Example №2

[test][test1]
lvl1.value = value1
lvl1.lvl2.value1 = 1

Will return undefined. Guys, your package is working well, it has cool name, and is very popular. Please add such support.

alvassin avatar May 21 '14 18:05 alvassin

@rlidwka Your example is a valid weirdness. Patch welcome.

@avasin Your first example is working as intended. Your second example is weird and I am not sure what the correct behavior is. Can you please post separate issues for what you expect the (2) case to do? It's not related to @rlidwka's issue.

isaacs avatar May 21 '14 22:05 isaacs

@isaacs hm.. i expected to get deep parsed object in the first example:

{
  lvl1: {
    value : value1
    lvl2  : {
        value1 : 1
    }
  }
}

Second example behaviour is expected to be the same as described here - deep object parsing.

alvassin avatar May 21 '14 22:05 alvassin

; config.ini
[file1.jpg]
size=10
date=2014

[file2.jpg]
size=11
date=2013

[other-file2.jpg]
size=10
date=2012

I would like to access a file with variable filenames sections. It would be nice to access the object with quotes.

var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'));
config["file1.jpg"].size = 6;
// config.file1.jpg.size = 6

You need to comment lines 101-120 to do this. One possible feature should be to be able to disable this with an option when invoking ini package.

mycaule avatar May 26 '14 16:05 mycaule

@mycaule , that's not how ini works. All ini parsers treat dots as path separators, and not doing so would be incompatible.

Instead, I would suggest to use this syntax:

[files."other-file2.jpg"]
size=10
date=2012
var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'));
config.files["file1.jpg"].size = 6;

This module doesn't support it, but I've seen parsers in other languages that do.

I implemented it here, can provide a patch if someone is interested.

rlidwka avatar Jun 17 '14 22:06 rlidwka

I have never seen a dot in a Windows config file section used that way. And this doesn't seem standard at all.

I think it is more like a hack to do some sort of mapping between JSON and INI.

mycaule avatar Jun 20 '14 09:06 mycaule

All ini parsers treat dots as path separators, and not doing so would be incompatible.

i cannot find this in the spec anywhere… is this something that evolved as a quasi-standard? is the statement really true for all ini parsers?

the idea to use a filename for the section key does seem legit. but this package makes parsing such ini files cumbersome at the very least.

p3k avatar Sep 18 '19 08:09 p3k

This is my solution, seems to be working to flatten it back as expected:

/**
 * Reduce the nested object back to a flat object by concatenating object keys with a `.`
 * @param obj Nested object
 * @returns {{}}
 */
function flattenIniObject(obj)
{
    function _flattenIniObject(obj, topLevel = [], resp = {}) {
        let props = {};
        for(let key in obj) {
            if(typeof obj[key] == 'object') {
                topLevel.push(key);
                resp = { ...resp, ..._flattenIniObject(obj[key], topLevel, resp)}
            }
            else
                props[key] = obj[key];
        }

        const topLevelName = topLevel.join(".");
        if(topLevelName !== '' && Object.keys(props).length > 0)
            resp = { ...resp, [topLevelName]: props}

        topLevel.pop();
        return resp;
    }

    return _flattenIniObject(obj);
}

let iniData = ini.parse(`; config.ini
[file1.jpg]
size=10
date=2014

[file2.jpg]
size=11
date=2013

[other-file2.jpg]
size=10
date=2012

; extra test cases
[file1]
strange=but okay

[level_1]
data=level 111
[level_1.level_2]
data=level 222
[level_1.level_2.level_3]
data=level 333
cool=yes
`)

const flat = flattenIniObject(iniData);
console.log(flat)

Outputs: image

rehanvdm avatar Feb 11 '23 02:02 rehanvdm