0

I am new to Python and learning python. I have a requirement where I need to convert Python object to Json String and Json String to Python object just like what we do in Jackson in Java. I am able to convert to Json String but while converting from json String to Python object, I am getting the following error.

AttributeError: 'dict' object has no attribute 'firstName'

I provide below the code details.

Employee Object as

import json

class Employee:

    def __init__(self):
        self._firstName = None
        self._lastName = None
        self._country = None

    @property
    def firstName(self):
        return self._firstName

    @firstName.setter
    def firstName(self, fName):
        self._firstName = fName

    @property
    def lastName(self):
        return self._lastName

    @lastName.setter
    def lastName(self, lName):
        self._lastName = lName

    @property
    def country(self):
        return self._country

    @country.setter
    def country(self, contryObj):
        self._country = contryObj

    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__,
                          sort_keys=True, indent=4)

    def toEmployee(self, jsonString):
        return json.loads(jsonString)

Country Object as

class Country:
    def __init__(self):
        self._countryName = None
        self._countryCode = None

    @property
    def countryName(self):
        return self._countryName

    @countryName.setter
    def countryName(self, cName):
        self._countryName = cName

    @property
    def countryCode(self):
        return self._countryCode

    @countryCode.setter
    def countryCode(self, cCode):
        self._countryCode = cCode

My test program is given below.

from toFromJson.Employee import Employee
from toFromJson.Country import Country


def checkEmp():
    emp = Employee()
    emp._firstName = "DD"
    emp._lastName = "Mishra"
    country = Country()
    country.countryCode = "12345"
    country.countryName = "India"
    emp.country = country

    print("Emp in toString format : ", emp.__dict__)
    print("--------------------- IN JSON -----------------")
    print(emp.toJSON())

    jsonString = '{ "_country": { "_countryCode": "7896", "_countryName": "India" }, "_firstName": "John", "_lastName": "Abrham" }'

    emp1 = emp.toEmployee(jsonString)
    print("Employee Name : ", emp1.firstName())
    print("Conveted object : ", emp1.__dict__)


if __name__ == "__main__":
    checkEmp()

What is the problem with this above code ? Please help me solve this. Besides I have few questions.

  1. Is there any framework in Python just like Jackson in Java to and from conversion ?
  2. How to achieve like @PropertyOrder("firstName","lastName","Country" ...etc) just like Jackson in java equivalent in python ?

Before posting this question, I have also gone through the following stackoverflow link How to make a class JSON serializable.

Sambit
  • 6,316
  • 4
  • 21
  • 54
  • 1
    All your properties are not necessary, just use normal attributes. – Daniel Apr 20 '19 at 16:50
  • Could please suggest, I have written like how we do in java with getter & setter. – Sambit Apr 20 '19 at 16:52
  • Also put everything in one file; one class per file is Java-only, too. – Daniel Apr 20 '19 at 16:56
  • Ok, accepted Sir, could please help me to solve this problem ? – Sambit Apr 20 '19 at 16:57
  • You are calling `emp1.firstName()`, but `emp1` is not `Employee` object. It simply stores the converted json, and hence its a dictionary. You need to call as `emp.firstName()`, but this won't serve your expected purpose. Have a look at https://stackoverflow.com/questions/10252010/serializing-class-instance-to-json – Kamal Nayan Apr 20 '19 at 17:44

1 Answers1

1

You have to define hooks for json.loads and json.dumps:

import json

class Employee:
    def __init__(self, firstName=None, lastName=None, country=None):
        self.firstName = firstName
        self.lastName = lastName
        self.country = country

class Country:
    def __init__(self, countryName=None, countryCode=None):
        self.countryName = countryName
        self.countryCode = countryCode

def to_json(obj):
    if isinstance(obj, Employee):
        return {
            'firstName': obj.firstName,
            'lastName': obj.lastName,
            'country': obj.country,
        }
    if isinstance(obj, Country):
        return {
            'countryName': obj.countryName,
            'countryCode': obj.countryCode,
        }
    raise TypeError

def from_json(obj):
    if 'firstName' in obj:
        return Employee(**obj)
    if 'countryName' in obj:
        return Country(**obj)
    return obj

def check_emp():
    emp = Employee("DD", "Mishra", Country("India", "12345"))
    json_string = json.dumps(emp, default=to_json, sort_keys=True, indent=4)
    print(json_string)
    emp1 = json.loads(k, object_hook=from_json)
    print("Employee Name : ", emp1.firstName)

if __name__ == "__main__":
    check_emp()
Daniel
  • 39,063
  • 4
  • 50
  • 76
  • Thanks Daniel, I got to learn a lot from you. Could you please explain Employee(**obj). I did not get it. Is it something like varargs in Java ? – Sambit Apr 21 '19 at 09:57