简体   繁体   English

将JSON字符串反序列化为Python中的对象

[英]Deserialize the JSON string into object in Python

I wrote this code to save and load an object into JSON. 我编写了这段代码,以将对象保存并加载到JSON中。 I faced to this error when I accessed into attribute: 访问属性时遇到了这个错误:

I use python json class to serialize the object and deserialize it. 我使用python json类来序列化对象并反序列化它。

AttributeError: 'dict' object has no attribute 'weeknumber' AttributeError:“ dict”对象没有属性“ 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. 您的代码本质上是正确的,但是您要混合很多方面,并以丑陋的方式解析JSON,从而为您提供当前结果,您无法直接访问属性,但是将创建的对象视为字典,并且需要通过密钥访问它。 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. 现在您可以简单地创建日历,现在要转储日历时,只需执行_mycal.To_JSON()并从JSON获取日历对象,则需要执行_mycal = json_calendar(json_data) ,您可以由于我们在特定的解析器中对其进行了解析,因此可以毫无问题地访问属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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