0

There is a good answer to How to convert JSON data into a Python object? but my JSON keys have invalid characters such as spaces and ":" in key strings.

Question is how to convert them to valid values so dot notation access can be used. For example {"key: 1":1} should be replaced with {"key__1"} so obj.key_1 notation could be used. Note that replacing " " an ":" with "_" would make a valid object attribute name from an invalid name.

martineau
  • 119,623
  • 25
  • 170
  • 301
user15420598
  • 107
  • 7

1 Answers1

0

I found this other answer Python recursively replace character in keys of nested dictionary? combining the two, you can access use dot notation to access keys that are not valid names for attributes. This is the content of test_json.json

   [
{"key 1": 1}
,{"key :2": 2}
]

And this is the complete processing

import json
from types import SimpleNamespace
def convert(k):
    k=k.replace(':',"_")  #replace : with _ since ":" not acceptable in syntax
    k=k.replace("(","_")
    k=k.replace(")","_")
    k=k.replace("/","_")
    return k.replace(' ', '_')  #replace space with underscore in string k

def change_keys(obj, convert):  #https://stackoverflow.com/questions/11700705/python-recursively-replace-character-in-keys-of-nested-dictionary
    """
    Recursively goes through the dictionary obj and replaces keys with the convert function.
    """
    if isinstance(obj, (str, int, float)):
        return obj
    if isinstance(obj, dict):
        new = obj.__class__()
        for k, v in obj.items():
            new[convert(k)] = change_keys(v, convert)
    elif isinstance(obj, (list, set, tuple)):
        new = obj.__class__(change_keys(v, convert) for v in obj)
    else:
        return obj
    return new
 

fpath=r'c:\temp\test_json.json'
with open (fpath) as f:
        x = json.load(f) #object_hook=lambda d: SimpleNamespace(**d)  
        
    xnew=change_keys(x,convert) #get rid of invalid characters spaces, ":", "("...
    xnew=json.loads(json.dumps(xnew),object_hook=lambda d: SimpleNamespace(**d)) #convert to new json data that has no spaces etc in names

Then you can use dot notation to access key values since spaces and other special characters have been replaced with "_" above to create valid names xnew[0].key_1

user15420598
  • 107
  • 7