简体   繁体   中英

Convert string into Dict / JSON

I'm trying to convert the following piece of data into a dict so I can have key:value pair and have them nested :

data="Group A\n name : rey\n age : 6\n status : active\n in role : 201\n weight : 25\n interests\n Out Side : 16016\n In Side : 0\n Out : 2804\n\n name : dan\n age : 5\n status : inactive\n in role : 201\n weight : 18\n interests\n Out Side : 16016\n In Side : 0\n Out : 2804\n\n"

Problem is, not all of them have : and some of them are supposed to be grouped together (ie part of Group A ). \\n line break definitely helps me in separating them.

Here's the result I'm hoping to get :

[
 {
  "Group A":
   [
    {"name": "rey", "age": "6", "status": "active"},
    {"name": "dan", "age": "5", "status": "inactive"}
   ]
 }
]

What do I have right now? I've separated some of them into dict with :

result = {}
for row in data.split('\n'):
  if ':' in row:
    key, value = row.split(':')
    result[key] = value.strip()

This outputs me :

{' name ': 'dan', ' weight ': '18', ' In Side ': '0', ' Out ': '2804', ' in role ': '201', ' status ': 'inactive', ' Out Side ': '16016', ' age ': '5'} But this messes up with the existing order in which the data is shown above - and not all of it came out.

I'm kind of capturing this data from an external program and so limited to only Python version 2.7. Any ideas would be super helpful!

You should find the pattern in your data :

  • Your data is separated by empty lines
  • The inner data start with space

Using those observations you can write :

def parse(data):
    aa = {}
    curRecord = None
    curGroup  = None

    for row in data.split('\n'):
        if row.startswith(' '): 
            # this is a new key in the inner record
            if ':' in row :
                if curRecord == None:
                    curRecord = {}
                    curGroup.append(curRecord)
                key, value = row.split(':')
                curRecord[key.strip()] = value.strip()
        elif row == '': 
            # this signal new inner record
            curRecord = None
        else: 
            # otherwise , it is a new group
            curRecord = None
            curGroup = []
            aa[row.strip()] = curGroup
    return aa

>>> import json
>>> print( json.dumps(parse(data)) );    
{"Group A": [{"name": "rey", ... }, {"name": "dan", ... }]}

I will use setdefault to create new lists within your Group. This will work for multiple Groups in case you have group B, C, D...

import json

def convert_string(data):
    result = {}
    current = ""
    key_no = -1
    for pair in data.split("\n"):
        if ':' not in pair:
            if "Group" in pair:
                result.setdefault(pair,[])
                current = pair
                key_no = -1
        elif "name" in pair:
            result[current].append({})
            key_no +=1
            key, value = pair.split(':')
            result[current][key_no][key.strip()] = value.strip()
        elif all(s not in pair.lower() for s in ("weight","in role","out","in side")):
            key, value = pair.split(':')
            result[current][key_no][key.strip()] = value.strip()
    return result

print (json.dumps(convert_string(d),indent=4))

{
    "Group A": [
        {
            "name": "rey",
            "age": "6",
            "status": "active"
        },
        {
            "name": "dan",
            "age": "5",
            "status": "inactive"
        }
    ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM