'Convert string like dict into dict format [closed]

I have a string that looks like the following:

{
change:"2.429993",
changePercent:"1.475316",
dayVolume:10222078,
exchange:NYQ,
id:CVX,
marketHours:1,
price:"167.14",
priceHint:4,
quoteType:8,
time:3304930430000,
}

I want to try and make this into a dict. I know that I can use json.loads to achieve this, however I do not know how to get the keys with double brackets.

Additionally, when I try parsing the string with the following:

type_of_dict.split(":")

It gives the following:

['{\nchange', '"2.429993",\nchangePercent', '"1.475316",\ndayVolume', '10222078,\nexchange', 'NYQ,\nid', 'CVX,\nmarketHours', '1,\nprice', '"167.14",\npriceHint', '4,\nquoteType', '8,\ntime', '3304930430000,\n}']

I can get it into a dict with a rather tedious process and was wondering if there are cleaner alternatives:

from collections import defaultdict
type_of_dict.split(":")
type_of_dict=[x.split(",\n") for x in type_of_dict]
keys=[x[1] for x in  type_of_dict[1:]][:-1]
keys  =[[x.split('\n') for x in type_of_dict[0]][0][1]] + keys
values = [x[0] for x in  type_of_dict[1:]]

symbols = defaultdict(list)
for k, v in zip(keys, values):
    symbols[k].append(v)
print(symbols)
defaultdict(<class 'list'>, {
    'change': ['"2.429993"'], 
    'changePercent': ['"1.475316"'], 
    'dayVolume': ['10222078'], 
    'exchange': ['NYQ'], 
    'id': ['CVX'], 
    'marketHours': ['1'], 
    'price': ['"167.14"'], 
    'priceHint': ['4'], 
    'quoteType': ['8'], 
    'time': ['3304930430000']
})

The script I used to grab the data:

import os
from subprocess import STDOUT, check_call as x
cmd1 = r'/Applications/StockSpy Realtime Stocks Quote.app/Contents/MacOS/StockSpy Realtime Stocks Quote'

with open(os.devnull, 'rb') as DEVNULL, open('output.txt', 'wb') as f:
    data=x(cmd1,  stdout=f, stderr=STDOUT)

with open('output.txt', 'r') as f:
    data=re.findall(r'\bsymbols:\s*\(\s*{[^{}]*}\s*\)', f.read()) 


Solution 1:[1]

Could you provide more test data/records?

import yaml
from pprint import pprint

data = """{
change:"2.429993",
changePercent:"1.475316",
dayVolume:10222078,
exchange:NYQ,
id:CVX,
marketHours:1,
price:"167.14",
priceHint:4,
quoteType:8,
time:3304930430000,
}"""

result_dict = yaml.safe_load(data.replace(':', ': '))
pprint(result_dict)

Result:

{'change': '2.429993',
 'changePercent': '1.475316',
 'dayVolume': 10222078,
 'exchange': 'NYQ',
 'id': 'CVX',
 'marketHours': 1,
 'price': '167.14',
 'priceHint': 4,
 'quoteType': 8,
 'time': 3304930430000}

After that if you want to cast types you can use pydantic:

from pydantic import BaseModel

class Record(BaseModel):
    change: float
    changePercent: float
    dayVolume: int
    exchange: str
    id: str
    marketHours: int
    price: float
    priceHint: int
    quoteType: int
    time: int


dict(Record(**result_dict))

Result:

{'change': 2.429993,
 'changePercent': 1.475316,
 'dayVolume': 10222078,
 'exchange': 'NYQ',
 'id': 'CVX',
 'marketHours': 1,
 'price': 167.14,
 'priceHint': 4,
 'quoteType': 8,
 'time': 3304930430000}

Solution 2:[2]

You can use a regular expression to add quotes around each key, then use ast.literal_eval() to parse it.

import ast
import re

dict_str = re.sub(r'^(.*?):', r"'\1':', type_of_dict)
result = ast.literal_eval(dict_str);

However, this will fail for exchange:NYQ. NYQ needs to be in quotes since it should be a string.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Barmar