484

I'm a little bit confused with JSON in Python. To me, it seems like a dictionary, and for that reason I'm trying to do that:

{
    "glossary":
    {
        "title": "example glossary",
        "GlossDiv":
        {
            "title": "S",
            "GlossList":
            {
                "GlossEntry":
                {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef":
                    {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}

But when I do print(dict(json)), I get an error.

How can I transform this string into a structure and then call json["title"] to obtain "example glossary"?

Neuron
  • 5,141
  • 5
  • 38
  • 59
Frias
  • 10,991
  • 9
  • 33
  • 40

4 Answers4

848

json.loads()

import json

d = json.loads(j)
print d['glossary']['title']
David Leon
  • 1,017
  • 8
  • 25
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 11
    What is the difference between json.load and json.loads ? – Shivam Agrawal May 05 '15 at 07:26
  • 6
    @ShivamAgrawal: Exactly what it says [on the tin](https://docs.python.org/2/library/json.html#json.load). – Ignacio Vazquez-Abrams May 05 '15 at 07:43
  • 81
    @ShivamAgrawal: The difference is that `.load()` parses a file object; `.loads()` parses a string / unicode object. – fyngyrz Sep 19 '16 at 17:07
  • 3
    It bothers me that the author of this function did not write a wrapper function to perform a type check on the data being passed in to automatically choose the right function to call. I also do not like the vague nomenclature used. Here is what I wrote to combat this: `def read_json(json_data): if (type(json_data) == str): return json.loads(json_data) elif (str(type(json_data)) == ""): return json.load(json_data)` I'm sure this can be improved, but now you can call `d = read_json(j)` on a json 'str' or 'file'. – Jacques Mathieu May 31 '18 at 16:32
  • 2
    @JacquesMathieu, Hi Jacques, thanx for your function, I did a minor improvement since I sometimes use dictionaries: def read_json(json_data): if (type(json_data) == str): # For strings return json.loads(json_data) elif (str(type(json_data)) == ""): #For files return json.load(json_data) elif (type(json_data) == dict): # For dictionaries return json.loads(json.dumps(json_data)) – Gabriel Aizcorbe Jun 02 '18 at 20:25
  • 1
    Any particular reason why you guys are doing this awkward string comparison instead of something like `isinstance(json_data, io.TexIOBase)`? There's tons of types that behave _like_ a file and I'm guessing it'd be useful to catch those as well. – Christian Jan 30 '20 at 20:18
118

When I started using json, I was confused and unable to figure it out for some time, but finally I got what I wanted
Here is the simple solution

import json
m = {'id': 2, 'name': 'hussain'}
n = json.dumps(m)
o = json.loads(n)
print(o['id'], o['name'])
Hussain
  • 5,057
  • 6
  • 45
  • 71
  • Why are you dumps(m) first? – Han Van Pham Nov 30 '18 at 09:47
  • I used it to demonstrate serialization and deserialization. Using `loads(..)` on `'{"id": 2, "name": "hussain"}'` should also be fine like the accepted answer. – Hussain Dec 03 '18 at 02:47
  • 1
    dumps and loads works perfect for me, while the accepted answer isn't, thanks a lot @Hussain for saving me a `time`, FYI, I'm trying to `loads` from dynamic strings with utf-8 encoding... – Mohammed Sufian Jul 27 '19 at 13:11
24

If you trust the data source, you can use eval to convert your string into a dictionary:

eval(your_json_format_string)

Example:

>>> x = "{'a' : 1, 'b' : True, 'c' : 'C'}"
>>> y = eval(x)

>>> print x
{'a' : 1, 'b' : True, 'c' : 'C'}
>>> print y
{'a': 1, 'c': 'C', 'b': True}

>>> print type(x), type(y)
<type 'str'> <type 'dict'>

>>> print y['a'], type(y['a'])
1 <type 'int'>

>>> print y['a'], type(y['b'])
1 <type 'bool'>

>>> print y['a'], type(y['c'])
1 <type 'str'>
kakhkAtion
  • 2,264
  • 22
  • 23
  • 1
    The string in your example is not JSON. – bfontaine Apr 25 '18 at 14:19
  • 1
    True. It evals to a dictionary tho, which can easily be loaded/dumped as JSON (and of course you might need a custom json encoder function if your dictionary has none json values). – kakhkAtion Apr 25 '18 at 19:08
  • 6
    No. You should *never* evaluate input data as a code. This may be your little pet project that uses data you trust, but bad code can be reused and bad practices repeated in real projects, leaving a big security code. – NetworkMeister Nov 16 '18 at 18:24
  • 1
    And that's why my answer starts with "if you trust the data source"! But true, this is more of a hack, and definitely not the best practice. – kakhkAtion Nov 19 '18 at 17:49
  • 2
    You can totally trust the data source if it's your own. This is actually useful to convert a stringified JS object into a dic into a proper JSON string. – Vadorequest Mar 06 '19 at 18:36
  • @NetworkMeister Sometimes, eval is not evil if and only if the string is hardcoded / self-generated / initiate for your own needs. Plus no one can manipulate the data – poring91 Nov 07 '19 at 05:21
22

use simplejson or cjson for speedups

import simplejson as json

json.loads(obj)

or 

cjson.decode(obj)
jassinm
  • 7,323
  • 3
  • 33
  • 42