Reading a json file and encoding problems

json, python, python-2.7

Solution

Assuming the JSON is formatted properly, the problem is that your code includes this check:

if k == "youtube":
    for innerk, innerv in k.iteritems():

Given that you just asked for `k` to be `"youtube"` (an instance of `str` or `unicode`), it won't make sense to expect `k` to have an `iteritems` method.

I believe instead you are expecting the associated `dict` that would have come along with `k`, something like this:

if k == "youtube":
    for innerk, innerv in value.iteritems():

I'm noticing from your JSON, though, that it looks like you should expect multiple `dict` variables to be loaded as the `list`-typed value for the case when `k == "youtube"`. In that case, you'll need to iterate over those elements first, asking for each one's `iteritems` separately:

if k == "youtube":
    for each_dict in value:
        for innerk, innerv in each_dict.iteritems():

or something along those lines. The final full code would be:

for item in j:        
    if item['trailers']:
        e = item['trailers']
        for k,value in e.iteritems():
            if k == "youtube":
                for each_dict in value:
                    for innerk, innerv in each_dict.iteritems():
                        if innerk == "source" :
                            print innerv

Aside from the first-order question, you should also take a look at the `dict` type's built-in method `get`, which allows you to safely get items from a dictionary and handle the case when they are missing gracefully. In your code, when you say `if item['trailers']:` this may not behave the way you expect.

First, if `trailers` is not a key to the dictionary, it will generate a `KeyError` instead of just skipping that conditional block. Secondly, if the value stored for the key value `trailers` evaluates to `False` in a `bool` context, the conditional block will also be skipped, even if you had wanted to handle it differently (for example, suppose that `None` is a sentinel value signaling that there is no data for `trailers` in that case, but it's due to a specific error that you want to log.

Meanwhile, if it's just an empty `dict` then that does mean you should simply skip the conditional block). This may not matter much in one-off data exploration, but in general it's good to become automatically conditioned to avoid these sorts of pitfalls, especially when the built-in types themselves make it very easy to handle things more gracefully.

Given all of this, a more Pythonic approach might be as follows:

for item in j:    
    y_tube = item.get('trailers', {}).get("youtube", [])
    for each_dict in y_tube:
        print each_dict.get("source", "Warning: no entry found for 'source'")

Problem

I would like to parse a JSON file and print `source` in this code fragment : ``` { "trailers": { "quicktime": [], "youtube": [ { "source": "mmNhzU6ySL8", "type": "Trailer", "name": "Trailer 1", "size": "HD" }, { "source": "CPTIgILtna8", "type": "Trailer", "name": "Trailer 2", "size": "Standard" } ], "id": 27205 }, ``` I wrote this code : ``` for item in j: if item['trailers']: e = item['trailers'] for k,value in e.iteritems(): if k == "youtube": for innerk, innerv in k.iteritems(): if innerk == "source" : print innerv ``` unfortunately I can't resolve this error : ``` for innerk, innerv in k.iteritems(): AttributeError: 'unicode' object has no attribute 'iteritems' ```

Original source