Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert Object with Properties to JSON without "_" in Python 3?

Tags:

python

json

I would like to convert an Python object into JSON-format.

The private attributes of the class User are defined using properties. The method to_Json() I have found here

class User:
  def __init__(self):
      self._name = None
      self._gender = None

  @property    
  def name(self):
    return self._name     

  @name.setter    
  def name(self, name):
      self._name = name

  @property    
  def gender(self):
      return self._gender     

  @gender.setter    
  def gender(self, gender):
    self._gender = gender

  def to_Json(self):
      return json.dumps(self, default=lambda o: o.__dict__, allow_nan=False, sort_keys=False, indent=4)

The output using this class and method is:

{
  "_name": "Peter",
  "_age": 26
}

What is the easiest way to get rid of the underscores in the JSON-format? (I want "name" instead of "_name") Removing the underscore in the class is not an option since I get an error (max. recursion depth). I think renaming the methods of the attributes would solve this problem, but is this the best solution here?

Renaming all keys before the json.dumbs (see here) is not a practical approach because I my class is more complex than the above example.

So, what is the best practice to convert a Python object into JSON-format as fast as possible?

like image 824
Steve Avatar asked Aug 04 '15 15:08

Steve


2 Answers

If the example code you posted mirrors your real code, there really isn't any reason for the properties at all. You could just do:

class User(object):
    def __init__(self):
        self.name = None
        self.age = None

since you're not really hiding anything from the user behind the underscores and properties anyway.

If you do need to do the transformation, I like to do it in a custom encoder:

class MyEncoder(json.JSONEncoder):
    def default(self, o):
        return {k.lstrip('_'): v for k, v in vars(o).items()}

json_encoded_user = json.dumps(some_user, cls=MyEncoder)
like image 72
mgilson Avatar answered Sep 28 '22 09:09

mgilson


In Python, you'd normally not use properties for basic attributes. You'd leave name and age to be directly accessible attributes. There is no need to wrap those in property objects unless you need to transform the data when getting or setting.

If you have good reasons to use attributes with underscores but reflect them as JSON dictionaries, you can transform your dictionary when converting to a dictionary:

object_dict = lambda o: {key.lstrip('_'): value for key, value in o.__dict__.items()}
return json.dumps(self, default=object_dict, allow_nan=False, sort_keys=False, indent=4)

Note that this does nothing to prevent collisions. If you have both a _name and a name attribute on your instance, you'll clobber one or the other.

like image 36
Martijn Pieters Avatar answered Sep 28 '22 11:09

Martijn Pieters