简体   繁体   中英

Deserialize the JSON string into object in Python

I wrote this code to save and load an object into JSON. I faced to this error when I accessed into attribute:

I use python json class to serialize the object and deserialize it.

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

# -*- coding: utf-8 -*-
import pickle
import pprint
from datetime import date
import datetime
import decimal
import json


class Jsonable(object):
    def __iter__(self):
        for attr, value in self.__dict__.iteritems():
            if isinstance(value, datetime.datetime):
                iso = value.isoformat()
                yield attr, iso
            elif isinstance(value, decimal.Decimal):
                yield attr, str(value)
            elif(hasattr(value, '__iter__')):
                if(hasattr(value, 'pop')):
                    a = []
                    for subval in value:
                        if(hasattr(subval, '__iter__')):
                            a.append(dict(subval))
                        else:
                            a.append(subval)
                    yield attr, a
                else:
                    yield attr, dict(value)
            else:
                yield attr, value


class MyCalendar(Jsonable):
    year = 0
    weeks = {}
    def __init__(self, _year,_weeks):
        self.year = _year
        self.weeks = _weeks;

class MyWeek(Jsonable):
    weeknumber = 0
    days = {}
    def __init__(self, _week,_days):
        self.weeknumber = _week   
        self.days = _days 

class MyDay(Jsonable):
    daynumber = 0
    courses = {}
    def __init__(self, _day,_courses):
        self.daynumber = _day  
        self.courses = _courses

class MyCourse(Jsonable):
    id = 0
    title = ''
    def __init__(self, _id,_title):
        self.id = _id 
        self.title = _title                  



def init():
    _myc = MyCalendar(date.today().year,[]);
    for wi in range(0, 52):
        _week = MyWeek(wi,[])
        for di in range(0, 5):
            _day = MyDay(di,[])
            for ci in range(0, 4):
                _course = MyCourse(ci,"empty")
                _day.courses.append(_course)
            _week.days.append(_day)
        _myc.weeks.append(_week)
    return _myc

def save(_t):
    with open('data2.txt', 'w') as outfile:
        json.dump(dict(_t), outfile)

def load():  
    _t =  init();
    with open('data2.txt', 'r') as infile:
        _t.__dict__ = json.loads(infile.read())
    return _t

def setCourse(_t,_weeknumnber,_dayumber,_course,_title): 
    _t.weeks[_weeknumnber].days[_dayumber].courses[_course].title  = _title
    return _t

_mycal = init();


setCourse(_mycal,1,2,3,"Python");
save(_mycal)
_mycal = load()
pprint.pprint( _mycal.weeks[1].weeknumber)

Your code is essentially correct, but you're mixing a lot of aspects and parsing the JSON in an ugly way that gives you the current results where you can't access the attributes directly but you treat the objects created as a dictionary and need to access it by key. To achieve your way, and keep the attributes in tact you'll need to create your own parser for the classes. I've made a quick copy of your code on my workspace:

import json

class MyCalendar:
    def __init__(self, _year, _weeks):
        self.year = _year
        self.weeks = _weeks

    def to_JSON(self):
        # Dumps the JSON correctly, passing over the __dict__ of the class to assmble it.
        return json.dumps(self, default=lambda o: o.__dict__)

class MyWeek:
    def __init__(self, _week, _days):
        self.weeknumber = _week
        self.days = _days

class MyDay:
    def __init__(self, _day, _courses):
        self.daynumber = _day
        self.courses = _courses

class MyCourse:
    def __init__(self, _id, _title):
        self.id = _id
        self.title = _title

def json_calendar(dct):
    year = dct['year'] # year, for quick reference.
    weeks = {} # our weeks, as a dict.

    for week in dct['weeks']: # iterate through the available weeks in the given dct.
        days = {} # our days, as a dict.
        for day in dct['weeks'][week]['days']: # iterate through the available days in the week.
            courses = {} # our courses, as a dict.
            for course in dct['weeks'][week]['days'][day]['courses']: # iterate through the available courses in the day.
                courseId = int(course) # course id
                courseTitle = dct['weeks'][week]['days'][day]['courses'][course]['title'] # course title

                courses[courseId] = MyCourse(courseId, courseTitle) # Assemble our courses into the courses dict.

            days[int(day)] = MyDay(day, courses) # Assemble our days into the day dict.

        weeks[int(week)] = MyWeek(week, days) # Assemble our weeks into the weeks dict.

    return MyCalendar(year, weeks) # Assemble and return our calendar.

Now you can simply create your calendar, and now when you're going to dump it you just need to do _mycal.To_JSON() and to get the calendar object from the JSON you need to do _mycal = json_calendar(json_data) and you can access the attributes without any issues since we parsed it in our specific parser.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM