-1

Trying to grab certain values from a json file and then 're-create' a new json file (sort of like a conversion). In the code below. I do the following:

  1. define function that returns an dictionary
  2. for each item in json, if function returns results, add results to list located inside parentObj dictionary

oldFile.json:

{
    "elements": [
        {
            "fieldValues": [
                {
                "id": "101",
                "value": "John"
                },
                {
                "id": "102",
                "value": "Doe"
                }
            ]
        },
        {
            "fieldValues": [
                {
                "id": "101",
                "value": "Jane"
                },
                {
                "id": "102",
                "value": "Doe"
                }
            ]
        }
    ]
}

file.py

import json
import os

output = {}
parentObj = {}
parentObj['entries'] = []

def grabVals(iCounter):
   # legend is a pre-determined dictionary matching ids with names (like first/last) 
   for myKey in subResults['elements'][iCounter]['fieldValues']:
        if myKey['id'] in legend:
            if 'value' in  myKey:
                newEntry = {legend[myKey['id']]: myKey['value']}
                output.update(newEntry) # first adds 'John', then 'Doe'
   # sample output below; next iteration would be 'Jane Doe'
   # {"First": "John", "Last": "Doe"}
   return output

subResults = json.loads(oldFile.json)

formCount = len(subResults['elements']) # subResults is the json above file. Grab total number of entries
for counter in range(0, formCount):
    if convertTime(formEntryStamp, formEntryID) == 'keep':  # self defined function (returns keep or None)       
        parentObj['entries'].append(grabVals(counter))
    else:
        pass

export = json.dumps(parent_obj, indent=4, sort_keys=False) # create new json based of dictionary

f = open("finished.json", "w")
f.write(export)
f.close()

Expected data in finished.json

{
    "entries": [
        {
            "First": "John",
            "Last": "Doe"
        },
        {
            "First": "Jane",
            "Last": "Doe"
        }
    ]
}

Actual data in finished.json:

{
    "entries": [
        {
            "First": "Jane",
            "Last": "Doe"
        },
        {
            "First": "Jane",
            "Last": "Doe"
        }
    ]
}

My question: How do I permanently write to parentObj? When output is changed in the function, the value inside parentObj is overwritten with new value. Does this have something to do mututable/immutable objects? Please let me know any further clarification is required.

Related links are similar, but refer to lists, whereas my is an object/dictionary:

Community
  • 1
  • 1
Kervvv
  • 751
  • 4
  • 14
  • 27
  • Um, what do you think `grabVals(counter)` is doing, because AFAIKT it always returns `{"result of": "conditional statement"}` and it never uses the argument passed to it... and what is with the `else: pass` which also seems to do nothing... – juanpa.arrivillaga Apr 26 '17 at 18:44
  • In other words, please provide a sample input, the output you are getting, and the output you are *expecting* – juanpa.arrivillaga Apr 26 '17 at 18:45
  • 1
    Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation. [Minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) applies here. We cannot effectively help you until you post your MCVE code and accurately describe the problem. We should be able to paste your given code into a text file and reproduce the problem. – Prune Apr 26 '17 at 19:05
  • I think we're stemming away from the true question. The problem is that once I add data to `parentObj` using a variable (i.e. `parentObj['entries'].append(myVar)` ), and then later `myVar` is reused and equals something else, whatever was previously written in `parentObj` gets changed to new value. Once again very similiar to linked question. @juanpa.arrivillaga @Prune – Kervvv Apr 26 '17 at 19:39
  • @Kervvv right, but we cannot reproduce your error, and you have a function that is only acting as a placeholder, and the root of the behavior you are seeing *likely stems from the particulars of that function*, so there is no way to know. But in any event, likely you are reusing the same dictionary, and simply *mutating it*, then appending that same dictionary to your list. – juanpa.arrivillaga Apr 26 '17 at 19:44
  • I added the instructions the function performs to my code, thank you for the instruction. I will look further into how to mutate a dictionary. – Kervvv Apr 26 '17 at 20:23

1 Answers1

0

After doing some reading on mutation of objects in python (link here), the code below solved my problem. Similar to what Juanpa said in the comments, I mutated the variable that was being re-used in my function (output). I assume with the code below, I am creating a copy thus leaving the original untouched.

def grabVals(iCounter, output=None):
    if output == None:
        output = {}
        for myKey in subResults['elements'][iCounter]['fieldValues']:
            if myKey['id'] in legend:
                if 'value' in  myKey:
                    newEntry = {legend[myKey['id']]: myKey['value']}
                    output.update(newEntry)
    return output
Kervvv
  • 751
  • 4
  • 14
  • 27