many open books

To JSON and Back Again

JavaScript Object Notation (JSON to its many friends) is a very useful string format for storing and retrieving complex data structures. Because pretty much every language provides tools for parsing and generating JSON strings, it’s also a handy way of sharing data between languages. You’re likely already familiar with PHP’s json_encode() which takes a data structure and serialises it to a string and its equally handy sibling json_decode() which converts a JSON string back into native data. As you’d expect, Python provides similar tools.

PHP Code Example:

Let’s build a simple array-based data structure and put it through a simple encode/decode round trip.

$business = [
    "name" => "Happy Widgets",
    "address" => [
        "street" => "14 Jolly Way",
        "city" => "Joyton"
    ]
];

$jsonstr = json_encode($business);
print gettype($jsonstr) . "\n";
print_r($jsonstr);
print "\n\n";
$decoded = json_decode($jsonstr, true);
print gettype($decoded) . "\n";
print_r($decoded);

So here we build a cut-down business entity (a flash of deja vu for me after years working on a large directory). We pass the multi-dimensional array to json_decode() and print the result along with its type. Then we pass the encoded string to json_decode() and convert it back into an array (note that second boolean argument which specifies that the function should return an array rather than a tree of objects). Finally we print the result and its type to demonstrate that we’ve come full circle.

Here’s the output:

string
{"name":"Happy Widgets","address":{"street":"14 Jolly Way","city":"Joyton"}}

array
Array
(
    [name] => Happy Widgets
    [address] => Array
        (
            [street] => 14 Jolly Way
            [city] => Joyton
        )

)

Python Code Example:

We will use a dictionary to construct a similar data structure and then walk it round the same encode and decode circuit.

business={
    "name": "Happy Widgets",
    "address": {
        "street": "14 Jolly Way",
        "city": "Joyton"
    }
}
jsonstr = json.dumps(business)
print(type(jsonstr))
print(jsonstr)

print()

decoded = json.loads(jsonstr)
print(type(decoded))
print(decoded)

As you can see, the core functionality here is provided by the json package. Although the output looks a little different, it demonstrates that we have converted the business dictionary first into a JSON string, and then back into a dictionary.

<class 'str'>
{"name": "Happy Widgets", "address": {"street": "14 Jolly Way", "city": "Joyton"}}

<class 'dict'>
{'name': 'Happy Widgets', 'address': {'street': '14 Jolly Way', 'city': 'Joyton'}}

Discussion

So both PHP and Python bundle support for JSON. As usual, both examples perform exactly the same tasks. We create a data structure that defines a business with an address element. We pass this to a function that encodes it as JSON and we print the result. Then we complete the journey by decoding the JSON once again. We confirm the type of the reconstructed data and then print it.

In Python, you need to import the json package. This provides tools for parsing and generating JSON strings and files.

So the json.dumps() function generates a JSON string. The json package also provides json.loads() to acquire a data structure from a string. If the string is not well formed the call will result in an JSONDecodeError, otherwise it will generate a Python object.

NOTE All keys in the data structure you wish to convert with json.dumps() or json.dump() should be of type str, int, float, bool or None. These will be translated into strings in the JSON output. Values should be JSON serialisable.

By default, the PHP json_decode() function will translate JSON objects into StdClass objects rather than a multidimensional associative array. You can change that by passing true as the optional second argument. json.loads() will generate a dictionary when given a JSON object ({}) to decode.

As they grow larger and more complex, JSON strings can be hard on the eyes. PHP lets you pretty print like this:

$prettyjson = json_encode($business,  JSON_PRETTY_PRINT);
print $prettyjson . "\n";

You can pretty print in Python by setting the indent parameter to the number of characters you would like to indent each level of the structure. This will also add newlines making for a nicely readable string. indent is set to None by default.

prettyjson = json.dumps(business, indent=4)
print(prettyjson)

The output for both these examples is identical.

{   
    "name": "Happy Widgets",
    "address": {
        "street": "14 Jolly Way",
        "city": "Joyton"
    }
}

If you want to write your JSON to a file from a Python script you could do it the PHP way and just print a pre-generated string. This is fine but can be expensive for a large data structure since you have to juggle a variable filled with data that you may not need in your script. Python’s json package provides json.dump(), a more direct way of getting the job done.

with open("outfiles/pybusiness2.json", "w") as dumpfile:
    json.dump(business, dumpfile)

json.dump() is identical to json.dumps() except that it requires an object that supports write() of the sort returned by open(). Instead of returning a JSON string it writes the JSON to the given output. In this case it writes to the file outfiles/pybusiness2.json.

As you might expect, you can also read from a JSON file with json.load():

with open("outfiles/pybusiness2.json", "r") as dumpfile:
    readbusiness = json.load(dumpfile)

Further Reading:


Stay up to date with the Python for PHP Programmers project


Yes! Please sign me up to this newsletter


Photo by Patrick Tomasso on Unsplash