3

I've been trying to parse a JSON file with Python's ijson library. This works when looking at second-level elements or when using a parser, but I'd prefer the convenience of looking at top level elements directly.

The JSON is basically formatted like this:

{"foo":{"a":1,"b":2},"bar":{"c":3,"d":4}}

So, nothing fancy. What I'd like to do is iterate through it in a way that yields "foo" and its value / "bar" and its value per iteration. (So just like if I were to json.loads this thing.) My code is the following - I know it's not going to yield both, I was just testing:

f=open('test')
i=ijson.items(f,'item')
for j in i:
    print j

The syntax of the items() function is what I got from stackoverflow.

However, strangely, the loop does take time, but it doesn't actually output anything. (Not even if I put a print 'qyx' in there, so I don't know what it's doing.) If I modify the items() function to parse foo.item, it does work, but what little info I can find indicates that it should work for the top level as well. Plus if I use the following, it works, but it's much more opaque:

i=ijson.parse(f)
for prefix, event, value in i:
   if not prefix or event == 'map_key' or ( '.' in prefix and event in ('start_map','end_map') ):
       continue
   print prefix, event, value

This would output

foo start_map None
foo.a number 1
foo.b number 2
foo end_map None
bar start_map None
bar.c number 3
bar.d number 4
bar end_map None

... which could be processed to yield "foo" and {"a":1,"b":2} etc, but it's much more of a hassle.

ma08
  • 3,654
  • 3
  • 23
  • 36
Pikaro
  • 148
  • 10

1 Answers1

0

Try this:

f = open('test')
json_obj = ijson.items(f,'').next() # '' loads everything as only one object.
for (key, value) in json_obj.items():
    print key + " -> " + str(value)
Salem
  • 12,808
  • 4
  • 34
  • 54
  • Wow, that's an approach that I'd never have thought of. Works great, thank you very much! Really drives the point home that I should do some more work with generators to thoroughly understand what's happening here. – Pikaro Aug 02 '14 at 09:21
  • 1
    Sorry to necro this, but just so any others know, this is basically the same as using json.load() and iterating the keys. It defeats the purpose of using ijson to dynamically load parts of the file into memory. – kahsm Aug 01 '21 at 13:07
  • Did not work for me. This is how I call it ij = ijson.items(fd,'').next() || and this is the error message I got: '_yajl2.items' object has no attribute 'next' What did I do wrong? – MMEL May 25 '22 at 23:45