3

I have an json array that looks like this:

{
        "inventory": [
            {
                "Name": "katt"
            },
            {
                "Name": "dog"
            }
        ]
}

And now I want to access this array in a program that I'm creating and remove a element, for example "Name": "dog". I'm not super familiar with how to work with json in python, but so far I have tried something like this:

import json

jsonfile = open("viktor.json", "r")
jsonObj = json.load(jsonfile)

jsonfile.close()

counter = 0
for item in range(len(jsonObj["inventory"])):
    print(jsonObj["inventory"][counter])
    print(type(jsonObj["inventory"][counter]))
    if jsonObj["inventory"][counter] == argOne:
        print("hej")
counter += 1

So first I read from the json and stores the data in a variable. Then I want to loop through the whole variable and see if I can find any match, and if so, I want to remove it. I think I can use a pop() method here or something? But I can't seem to get my if-statement to work properly since the jsonObj["inventory"][counter] is a dict and argOne is a string.

What can I do instead of this? Or what I'm missing?

Coderji
  • 7,655
  • 5
  • 37
  • 51
anderssinho
  • 298
  • 2
  • 7
  • 21
  • 1
    I presume the argOne is a name you're looking for in the dict, if so, `if jsonObj["inventory"][counter]['Name'] == argOne:` should works. – slackmart Sep 15 '16 at 05:53
  • 1
    Yes, `jsonObj["inventory"][counter]` will be a dict. If you are comparing value of `Name`, try this: `jsonObj['inventory'][counter]['Name'] == argOne`. – coder.in.me Sep 15 '16 at 05:54
  • @slackmart it's exactly that I'm looking for. Will try that – anderssinho Sep 15 '16 at 05:55
  • @slackmart and arvindpdmn I get this error when I try that: if jsonObj["inventory"][counter]['name'] == argOne: KeyError: 'name' – anderssinho Sep 15 '16 at 05:56
  • 1
    In fact, use of `range(len())` is not pythonic. Improve it by looping on item: `for item in jsonObj['inventory']: ...`. Variable `counter` is not needed. – coder.in.me Sep 15 '16 at 05:56
  • @arvindpdmn okay I will update it then. But still that part worked before, I just can't get the If to work as I want – anderssinho Sep 15 '16 at 05:58
  • @anderssinho try again with `['Name']`. Remember it's case sensitive. – slackmart Sep 15 '16 at 05:58
  • @slackmart Now I have like this; for item in jsonObj['inventory']: if jsonObj["inventory"]['Name'] == argOne: print("hej") Or did I not understand what you meant because this doesnt work eiter – anderssinho Sep 15 '16 at 06:00
  • 1
    @arvindpdmn recommendation is okay, but the syntax will change to `if item['Name'] == argOne:` – slackmart Sep 15 '16 at 06:04
  • @arvindpdmn aha okay! can you try ti briefly explain why this works for me so I can learn to next time? :) – anderssinho Sep 15 '16 at 06:06

2 Answers2

4

Making the change suggested by @arvindpdmn (to be more pythonic).

for index, item in enumerate(jsonObj["inventory"]):
    print(item)
    print(type(item))  # Here we have item is a dict object
    if item['Name'] == argOne:  # So we can access their elements using item['key'] syntax
        print(index, "Match found")

The for loop is responsible to go through the array, which contains dict objects, and for each dict it will create a item variable that we use to try to get a match.

edit In order to remove the element if it is in the list, I suggest you to use this:

new_list = []
for item in jsonObj["inventory"]:
    if item['Name'] is not argOne:  # add the item if it does not match
        new_list.append(item)

This way you will end with the list you want (new_list).

# Or shorter.. and more pythonic with comprehensions lists.
new_list = [item for item in jsonObj['inventory'] if item['Name'] is not argOne]
slackmart
  • 4,754
  • 3
  • 25
  • 39
  • 1
    Great thanks mate! Can I also ask how to get the index of the match so I instead of my print("hej") Kan use the item.pop(x) and remove the element from the object? – anderssinho Sep 15 '16 at 06:14
  • Glad to help you! – slackmart Sep 15 '16 at 06:15
  • use the enumerate function : `for index, item in enumerate(jsonObj["inventory"]) :`. – Tony Suffolk 66 Sep 15 '16 at 06:16
  • @TonySuffolk66: `enumerate` will bring me an index, and the dict element itself, but in this code, I don't see the need to use it. – slackmart Sep 15 '16 at 06:20
  • @slackmart - The OP asked in a comment how to get the index so he could use the pop method against the index. I agree your code does not need enumerate.. – Tony Suffolk 66 Sep 15 '16 at 06:22
  • @slackmart, how can I see the index in you example then you mean without this enumerate? – anderssinho Sep 15 '16 at 06:22
  • Sorry I don't see the comment where the index is requested. So if you need the index, you can use the syntax provided by @TonySuffolk66 and the rest of the code just will works as expected. – slackmart Sep 15 '16 at 06:25
  • @anderssinho - you shouldn't be using `pop` on an object while iterating (using the `for` loop across the the same object). It can lead to some very odd bugs. – Tony Suffolk 66 Sep 15 '16 at 06:25
  • @TonySuffolk66, is it better to create a temp object and store all the data I want and when I find a match, skip that one and then write it back to the file then? – anderssinho Sep 15 '16 at 06:26
  • @slackmart, sorry that I make you go through all this trouble :p But you said I should't use the pop to remove right? What is recommended then? – anderssinho Sep 15 '16 at 06:29
  • What are you trying to archive when you say removing? – slackmart Sep 15 '16 at 06:30
  • @slackmart inside my json I have some elements. In this function inside my program I'm creating I want to delete an specific element in the json and update the json file. So for example if I run the program and decide I want to remove dog from the json. Then I want to see if dog is inside json, if it's inside then delete the entry and update json. – anderssinho Sep 15 '16 at 06:32
  • Ok, I'm going to update again to remove the item if it is inside the list. – slackmart Sep 15 '16 at 06:33
  • @anderssinho I don't fully understand what you are trying to do - but if you are trying to write out new json file with the same contents but one removed, then copying items as you find them to a new structure is "probably" the simplest at this stage. Of course if the only thing you are doing is creating a new version with some items removed then creating new version with a list comprehension might well be far more effective. – Tony Suffolk 66 Sep 15 '16 at 06:33
  • @slackmart, now when I try your example I don't get any matches to argOne anymore. The new list is excatly like the old one. Is there some other way to compare? – anderssinho Sep 15 '16 at 06:43
  • 1
    change the `is not ` by `!=` I'm sleepy – slackmart Sep 15 '16 at 06:44
  • @slackmart ah that's beacase is checks if it's the same place where != checks if the are the same right? Thanks now everything works like a clock! – anderssinho Sep 15 '16 at 06:46
  • Amm. BTW both ways works for me. For reference look at this http://stackoverflow.com/a/133024/977593 – slackmart Sep 15 '16 at 06:53
1

You can use filter:

In [11]: import json

In [12]: with open("viktor.json", "r") as f:
    ...:     jsonObj = json.load(f)
    ...:     

In [13]: argOne = 'katt' #Let's say

In [14]: jsonObj['inventory'] = list(filter(lambda x: x['Name'] != argOne, jsonObj['inventory']))

In [15]: jsonObj
Out[15]: {'inventory': [{'Name': 'dog'}]}
Nehal J Wani
  • 16,071
  • 3
  • 64
  • 89