Refactoring the encode function

The encoding function shouldn't expose information on the classes being converted into JSON. To keep each class properly encapsulated, it seems better to refactor the creation of a serialized representation into each application class. We'd rather not pile all of the encoding rules into a function outside the class definitions.

To do this with library classes, such as datetime, we would need to extend datetime.datetime for our application. This leads to making our application use the extended datetime instead of the datetime library. This can become a bit of a headache to avoid using the built-in datetime classes. Consequently, we may elect to strike a balance between our customized classes and library classes. Here are two class extensions that will create JSON-encodable class definitions. We can add a property to Blog:

    @property 
    def _json( self ) -> Dict[str, Any]: 
        return dict(
__class__=self.__class__.__name__,
__kw__={}, __args__=[self.title, self.entries] )

This property will provide initialization arguments that are usable by our decoding function. We can add this property to Post:

    @property 
    def _json(self) -> Dict[str, Any]: 
        return dict( 
            __class__=self.__class__.__name__, 
            __kw__=dict( 
                date= self.date, 
                title= self.title, 
                rst_text= self.rst_text, 
                tags= self.tags, 
            ), 
            __args__=[] 
        ) 

As with Blog, this property will provide initialization arguments that are usable by our decoding function. The type hint emphasizes the intermediate, JSON-friendly representation of Python objects as Dict[str, Any]

These two properties let us modify the encoder to make it somewhat simpler. Here's a revised version of the default function provided for encoding:

def blog_encode_2(object: Union[Blog, Post, Any) -> Dict[str, Any]: 
    if isinstance(object, datetime.datetime): 
        return dict( 
            __class__="datetime.datetime", 
            __args__=[], 
            __kw__=dict( 
                year= object.year, 
                month= object.month, 
                day= object.day, 
                hour= object.hour, 
                minute= object.minute, 
                second= object.second, 
            ) 
        ) 
    else: 
        try: 
            encoding = object._json
        except AttributeError: 
            encoding = json.JSONEncoder().default(o) 
        return encoding 

There are two kinds of cases here. For a datetime.datetime library class, this function includes the serialization, exposing details of the implementation. For our Blog and Post application classes, we can rely on these classes having a consistent _json() method that emits a representation suitable for encoding.

Let's see how to standardize a date string in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset