Convert Dot notation string into nested Python object with Dictionaries and arrays

前端 未结 1 830
有刺的猬
有刺的猬 2021-01-13 10:07

Background

For some background, I\'m trying to create a tool that converts worksheets into API calls using Python 3.5

For the conversion of the table cells

相关标签:
1条回答
  • 2021-01-13 10:39

    So I'm not sure if there are any caveats in this solution, but this appears to work for some of the use cases i'm throwing at it:

    import json, re
    def build_job():
    
        def branch(tree, vector, value):
            
            # Originally based on https://stackoverflow.com/a/47276490/2903486
    
            # Convert Boolean
            if isinstance(value, str):
                value = value.strip()
    
                if value.lower() in ['true', 'false']:
                    value = True if value.lower() == "true" else False
    
            # Convert JSON
            try:
                value = json.loads(value)
            except:
                pass
            
            key = vector[0]
            arr = re.search('\[([0-9]+)\]', key)
                
            if arr:
                
                # Get the index of the array, and remove it from the key name
                arr = arr.group(0)
                key = key.replace(arr,'')
                arr = int(arr.replace('[','').replace(']',''))
                
                if key not in tree:
                    
                    # If we dont have an array already, turn the dict from the previous 
                    # recursion into an array and append to it
                    tree[key] = []
                    tree[key].append(value \
                        if len(vector) == 1 \
                        else branch({} if key in tree else {},
                                    vector[1:],
                                    value))
                else:
                    
                    # Check to see if we are inside of an existing array here
                    isInArray = False
                    for i in range(len(tree[key])):
                        if tree[key][i].get(vector[1:][0], False):
                            isInArray = tree[key][i][vector[1:][0]]
                            
                    if isInArray and arr < len(tree[key]) \
                       and isinstance(tree[key][arr], list):
                        # Respond accordingly by appending or updating the value
                        tree[key][arr].append(value \
                            if len(vector) == 1 \
                            else branch(tree[key] if key in tree else {},
                                        vector[1:],
                                        value))
                    else:
                        # Make sure we have an index to attach the requested array to
                        while arr >= len(tree[key]):
                            tree[key].append({})
    
                        # update the existing array with a dict
                        tree[key][arr].update(value \
                            if len(vector) == 1 \
                            else branch(tree[key][arr] if key in tree else {},
                                        vector[1:],
                                        value))
                
                # Turn comma deliminated values to lists
                if len(vector) == 1 and len(tree[key]) == 1:
                    tree[key] = value.split(",")
            else:
                # Add dictionaries together
                tree.update({key: value \
                    if len(vector) == 1 \
                    else branch(tree[key] if key in tree else {},
                                vector[1:],
                                value)})
            return tree
    
        file = [{
            "one.array[0].dict.dont-worry-about-me": "some value",
            "one.array[0].dict.arrOne[0]": "1,2,3",
            "one.array[0].dict.arrTwo[1]": "4,5,6",
            "one.array[1].x.y[0].z[0].id": "789"
        }]
        rowList = []
        for row in file:
            rowObj = {}
            for colName, rowValue in row.items():
                rowObj.update(branch(rowObj, colName.split("."), rowValue))
            rowList.append(rowObj)
        return rowList
    print(json.dumps(build_job(), indent=4))
    

    Result:

    [
        {
            "one": {
                "array": [
                    {
                        "dict": {
                            "dont-worry-about-me": "some value",
                            "arrOne": [
                                "1",
                                "2",
                                "3"
                            ],
                            "arrTwo": [
                                "4",
                                "5",
                                "6"
                            ]
                        }
                    },
                    {
                        "x": {
                            "y": [
                                {
                                    "z": [
                                        {
                                            "id": 789
                                        }
                                    ]
                                }
                            ]
                        }
                    }
                ]
            }
        }
    ]
    
    0 讨论(0)
提交回复
热议问题