kohi
kohi

Reputation: 974

How we convert string into json

I want to convert ansible-init file into json. So, I just use this code: common_shared file:

 [sql]
 x.com
 [yps_db]
 y.com
 [ems_db]
 c.com
 [scc_db]
 d.com

 [all:vars]
 server_url="http://x.com/x"
 app_host=abc.com
 server_url="https://x.com"

 [haproxy]
 1.1.1.1    manual_hostname=abc instance_id=i-dddd
 2.2.2.2     manual_hostname=xyz instance_id=i-cccc

For converting Ansible INI file in JSON:

 import json

 options= {} 
 f = open('common_shared')
 x = f.read()
 config_entries = x.split()
 for key,value in zip(config_entries[0::2], config_entries[1::2]):
  cleaned_key = key.replace("[",'').replace("]",'')
  options[cleaned_key]=value

  print json.dumps(options,indent=4,ensure_ascii=False)

But it will print this result:

{
"scc_db": "xxx", 
"haproxy": "x.x.x.x", 
"manual_hostname=xxx": "instance_id=xx", 
"ems_db": "xxx", 
"yps_db": "xxx", 
"all:vars": "yps_server_url=\"xxx\"", 
"1.1.1.5": "manual_hostname=xxx", 
"sql": "xxx", 
"xxx": "scc_server_url=xxxx\""
}

But I wanted to print result in proper JSON format but not able to understand how. I tried config parser but didn't get help to print it in desired format.

Upvotes: 1

Views: 1579

Answers (2)

Christian Witts
Christian Witts

Reputation: 11585

You can use ConfigParser to read in your file, and then do the conversion to a dict to dump.

from ConfigParser import ConfigParser
from collections import defaultdict

config = ConfigParser()
config.readfp(open('/path/to/file.ini'))

def convert_to_dict(config):
    config_dict = defaultdict(dict)
    for section in config.sections():
        for key, value in config.items(section):
            config_dict[section][key] = value

    return config_dict

print convert_to_dict(config)

EDIT

As you stated in your comment, some line items are just 'things' with no value, the below might work for you.

import re
from collections import defaultdict

SECTION_HEADER_RE = re.compile('^\[.*\]$')
KEY_VALUE_RE = re.compile('^.*=.*$')

def convert_ansible_to_dict(filepath_and_name):
    ansible_dict = defaultdict(dict)
    with open(filepath_and_name) as input_file:
        section_header = None
        for line in input_file:
            if SECTION_HEADER_RE.findall(line.strip()):
                section_header = SECTION_HEADER_RE.findall(line.strip())[0]
            elif KEY_VALUE_RE.findall(line.strip()):
                if section_header:
                    # Make sure you have had a header section prior to the line
                    key, value = KEY_VALUE_RE.findall(line.strip())[0].split('=', 1)
                    ansible_dict[section_header][key] = value
            else:
                if line.strip() and section_header:
                    # As they're just attributes without value, assign the value None
                    ansible_dict[section_header][line.strip()] = None

    return ansible_dict

This is a naive approach, and might not catch all corner cases for you, but perhaps it's a step in the right direction. If you have any 'bare-attributes' prior to your first section header, they will not be included in the dictionary as it would not know where to apportion it to, and the regex for key=value pairs is working on the assumption that there will be only 1 equals sign in the line. I'm sure there might be many other cases I'm not seeing right now, but hopefully this helps.

Upvotes: 2

Jonathan Miller
Jonathan Miller

Reputation: 337

Christian's answer is the correct one: Use ConfigParser. Your issue with his solution is that you have an incorrectly formatted INI file.

You need to change all your properties to:

key=value
key: value

e.g.
[sql]
aaaaaaa: true

https://wiki.python.org/moin/ConfigParserExamples

https://en.wikipedia.org/wiki/INI_file#Keys_.28properties.29

Upvotes: 0

Related Questions