Programming
python json python-3.x python-2.7 stringio
Updated Wed, 29 Jun 2022 21:37:05 GMT

Porting json.dump into StringIO code to python 3


I'm porting a Python 2 application to Python 3. Currently running Python2.7 but, updating code to pass pylint --py3k tests, I have run into a problem with this:

def json_resource_file(baseurl, jsondata, resource_info):
    """
    Return a file object that reads out a JSON version of the supplied entity values data. 
    """
    response_file = StringIO()
    json.dump(jsondata, response_file, indent=2, separators=(',', ': '), sort_keys=True)
    response_file.seek(0)
    return response_file

It works fine with:

from StringIO import StringIO

but StringIO.StringIO doesn't exist in Python3 (according to pylint), so using:

from io import StringIO

I get an error: "TypeError: unicode argument expected, got 'str'" (This is running under Python 2 - I'm still preparing the ground, so to speak, and am not planning to use Python 3 until I have done as much preparation and testing as I can under Python 2.)

By way of some experimentation, I tried using BytesIO from io, but that gives a different error "TypeError: 'unicode' does not have the buffer interface".

Clearly, the Python2 version of json.dump is writing str values to the supplied file object. I think the Python3 version of json.dump also writes str (i.e. Unicode) values.

So my question is: is there an easy way to dump JSON to a StringIO memory buffer that works with Python 2 and 3?

Notes

  1. I realize I could use json.dumps and coerce the result to whatever type StringIO expects, but that all seems rather heavy-handed.

  2. I'm also using the following future imports as part of my porting process:

    from __future__ import (unicode_literals, absolute_import, division, print_function)
    
  3. Currently, a solution I'm thinking of is to test the python version and import a different version of StringIO accordingly, but that would violate the "Use feature detection instead of version detection" principle.

  4. In most of my code, using from io import StringIO appears to work fine for situations that I use StringIO. It's the specific case of using a StringIO with json.dump that has caused me a few problems.




Solution

Use six's StringIO

from six.moves import StringIO