I have a dictionary like string as below:
str = "Access AR1:\n\tTargets: \n\t\tManagement Name:csw_1\n\t\tObject Name:csw_obj_1\n\t\tdetails:103\n\t\tManagement Name:csw_123\n\t\tObject Name:csw_obj_134\n\t\tdetails:123\n\tSources: \n\t\tIP:10.20.30.40\n\t\tSubnet Mask:255.255.255.255\nAccess AR2:\n\tTargets: \n\t\tManagement Name:csw_2\n\t\tObject Name:csw_obj_2\n\t\tdetails:110\n\t\tManagement Name:csw_431\n\t\tObject Name:csw_obj_21\n\t\tdetails:134\n\tSources: \n\t\tIP:10.20.10.10\n\t\tSubnet Mask:255.255.255.192"
and this goes on in the same format, which would look like:
Access AR1:
Targets:
Management Name:csw_1
Object Name:csw_obj_1
details:103
Management Name:csw_123
Object Name:csw_obj_134
details:123
Sources:
IP:10.20.30.40
Subnet Mask:255.255.255.255
Access AR2:
Targets:
Management Name:csw_2
Object Name:csw_obj_2
details:110
Management Name:csw_431
Object Name:csw_obj_21
details:134
Sources:
IP:10.20.10.10
Subnet Mask:255.255.255.192
and this need to be changed to:
str = {"Access AR1": { "Targets": [{"Management Name:csw_1", "Object Name":"csw_obj_1", "details":"103"}, {"Management Name:csw_123", "Object Name":"csw_obj_134", "details":"123"}]
"Sources": {"IP":"10.20.30.40", "Subnet Mask": "255.255.255.255"}
},
"Access AR2": { "Targets": [{"Management Name:csw_2", "Object Name":"csw_obj_2", "details":"110"}, {"Management Name:csw_431", "Object Name":"csw_obj_21", "details":"133"}]
"Sources": {"IP":"10.20.10.10", "Subnet Mask": "255.255.255.192"}
}
}
I tried ast.literal_eval, eval
and ended up with an error.
To convert a Python string to a dictionary, use the json. loads() function. The json. loads() is a built-in Python function that converts a valid string to a dict.
You can easily convert python string to the dictionary by using the inbuilt function of loads of json library of python. Before using this method, you have to import the json library in python using the “import” keyword.
Second, a dictionary key must be of a type that is immutable. For example, you can use an integer, float, string, or Boolean as a dictionary key.
You can use the ast.literal_eval () function to convert the string representation of a dictionary to a dictionary in Python. The following is the syntax. It returns a dictionary. We get the result as a dictionary. Alternatively, you can use the json.loads () function to convert a string representation of a dictionary to a dictionary in Python.
The key and its corresponding value are separated by a colon (:). And each key:value pair in the dictionary is separated by a comma (,). A dictionary in Python is always enclosed in the curly brackets {}.
The most important feature of the python dictionaries is that they don’t allow polymorphism. Also, the keys in the dictionary are case-sensitive. Therefore, the uppercase and lowercase keys are considered different from each other. Later, you can access the dictionary data by referring to its corresponding key name.
Your string is nearly yaml - replace the \t with one or more spaces and it loads as YAML.
First:
pip install pyyaml
Then this code works:
import yaml
import pprint
str = "Access AR1:\n\tTargets: \n\t\tManagement Name:csw_1\n\t\tObject Name:csw_obj_1\n\t\tdetails:103\n\tSources: \n\t\tIP:10.20.30.40\n\t\tSubnet Mask:255.255.255.255\nAccess AR2:\n\tTargets: \n\t\tManagement Name:csw_2\n\t\tObject Name:csw_obj_2\n\t\tdetails:110\n\tSources: \n\t\tIP:10.20.10.10\n\t\tSubnet Mask:255.255.255.192"
str1 = str.replace( '\t', ' ' )
res = yaml.load(str1)
pprint.pprint( res )
Output:
{'Access AR1': {'Sources': 'IP:10.20.30.40 Subnet Mask:255.255.255.255',
'Targets': 'Management Name:csw_1 Object Name:csw_obj_1 '
'details:103'},
'Access AR2': {'Sources': 'IP:10.20.10.10 Subnet Mask:255.255.255.192',
'Targets': 'Management Name:csw_2 Object Name:csw_obj_2 '
'details:110'}}
Or, if you really want this as a string then:
str = repr(res)
UPDATE
Just realised that e.g. 'Managent Name:csw_1' isn't being detected as a key:value. Needed a regex re.sub()
to split these onto separate lines to fix this:
import yaml
import pprint
import re
str = "Access AR1:\n\tTargets: \n\t\tManagement Name:csw_1\n\t\tObject Name:csw_obj_1\n\t\tdetails:103\n\tSources: \n\t\tIP:10.20.30.40\n\t\tSubnet Mask:255.255.255.255\nAccess AR2:\n\tTargets: \n\t\tManagement Name:csw_2\n\t\tObject Name:csw_obj_2\n\t\tdetails:110\n\tSources: \n\t\tIP:10.20.10.10\n\t\tSubnet Mask:255.255.255.192"
# replace \t with four-space indent
str1 = str.replace( '\t', ' ' )
# further tweak to split sub-keys like " Management Name:csw_1" onto separate lines
str1 = re.sub(r"^(\s+)(.*?\S:)(\S.*)", r"\1\2\n\1 \3",str1,flags=re.MULTILINE )
res = yaml.load(str1)
pprint.pprint( res )
This is the string after tweaks:
Access AR1:
Targets:
Management Name:
csw_1
Object Name:
csw_obj_1
details:
103
Sources:
IP:
10.20.30.40
Subnet Mask:
255.255.255.255
Access AR2:
Targets:
Management Name:
csw_2
Object Name:
csw_obj_2
details:
110
Sources:
IP:
10.20.10.10
Subnet Mask:
255.255.255.192
Result:
{'Access AR1': {'Sources': {'IP': '10.20.30.40',
'Subnet Mask': '255.255.255.255'},
'Targets': {'Management Name': 'csw_1',
'Object Name': 'csw_obj_1',
'details': 103}},
'Access AR2': {'Sources': {'IP': '10.20.10.10',
'Subnet Mask': '255.255.255.192'},
'Targets': {'Management Name': 'csw_2',
'Object Name': 'csw_obj_2',
'details': 110}}}
Hello this is the solution you need
strr = "Access AR1:\n\tTargets: \n\t\tManagement Name:csw_1\n\t\tObject Name:csw_obj_1\n\t\tdetails:103\n\tSources: \n\t\tIP:10.20.30.40\n\t\tSubnet Mask:255.255.255.255\nAccess AR2:\n\tTargets: \n\t\tManagement Name:csw_2\n\t\tObject Name:csw_obj_2\n\t\tdetails:110\n\tSources: \n\t\tIP:10.20.10.10\n\t\tSubnet Mask:255.255.255.192"
nvstr=strr.replace("\n\t\t","-").replace("\n\t","+")
#print(nvstr)
nvdd={}
for u in nvstr.split("\n"):
#print(u)
dts=u.split("+")
nvdd[dts[0]]={}
for el in dts[1:]:
dts1=el.split("-")
nvdd[dts[0]][dts1[0][:-1]]={}
for el1 in dts1[1:]:
k,v=el1.split(":")
nvdd[dts[0]][dts1[0][:-1]][k]=v
print(nvdd)
You can use recursion to convert the input to a dictionary, without having to make any adjustments to the string itself beforehand:
import re
s = "Access AR1:\n\tTargets: \n\t\tManagement Name:csw_1\n\t\tObject Name:csw_obj_1\n\t\tdetails:103\n\tSources: \n\t\tIP:10.20.30.40\n\t\tSubnet Mask:255.255.255.255\nAccess AR2:\n\tTargets: \n\t\tManagement Name:csw_2\n\t\tObject Name:csw_obj_2\n\t\tdetails:110\n\tSources: \n\t\tIP:10.20.10.10\n\t\tSubnet Mask:255.255.255.192"
def to_dict(d):
k, v, r = None, [], {}
for *b, a in d:
if not b:
if k is not None:
if not v:
r[j[0]] = (j:=re.split(':\s*', k))[-1]
else:
r[re.split(':\s*', k)[0]] = to_dict(v)
k, v = a, []
else:
v.append([*b[1:], a])
if k is not None:
if not v:
r[j[0]] = (j:=re.split(':\s*', k))[-1]
else:
r[re.split(':\s*', k)[0]] = to_dict(v)
return r
import json
new_s = [re.findall('\t|[^\t]+$', i) for i in s.split('\n')]
print(json.dumps(to_dict(new_s), indent=4))
Output:
{
"Access AR1": {
"Targets": {
"Management Name": "csw_1",
"Object Name": "csw_obj_1",
"details": "103"
},
"Sources": {
"IP": "10.20.30.40",
"Subnet Mask": "255.255.255.255"
}
},
"Access AR2": {
"Targets": {
"Management Name": "csw_2",
"Object Name": "csw_obj_2",
"details": "110"
},
"Sources": {
"IP": "10.20.10.10",
"Subnet Mask": "255.255.255.192"
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With