How to exclude specific fields on serialization with jsonpickle?
Asked Answered
S

2

21

I'm using SQLAlchemy extension with Flask. While serializing my models (which are also used for database operations) using jsonpickle, I want some specific attributes to be ignored. Is there a way that allows me to set those rules?

SQLAlchemy adds an attribute named _sa_instance_state to the object. In a word, I do not want this field to be in the JSON output.

Sharpen answered 9/8, 2013 at 13:10 Comment(0)
S
30

You cannot tell the default class pickler to ignore something, no.

jsonpickle does support the pickle module __getstate__ and __setstate__ methods. If your classes implement those two methods, whatever is returned is then used by jsonpickle to represent the state instead. Both methods do need to be implemented.

If __getstate__ is not implemented, jsonpickle uses the __dict__ attribute instead, so your own version merely needs to use that same dictionary, remove the _sa_instance_state key and you are done:

def __getstate__(self):
    state = self.__dict__.copy()
    del state['_sa_instance_state']
    return state

def __setstate__(self, state):
    self.__dict__.update(state)

Whatever __getstate__ returns will be processed further, recursively, there is no need to worry about handling subobjects there.

If adding __getstate__ and __setstate__ is not an option, you can also register a custom serialization handler for your class; the disadvantage is that while __getstate__ can get away with just returning a dictionary, a custom handler will need to return a fully flattened value.

Scurvy answered 9/8, 2013 at 13:30 Comment(2)
Adding __getstate__ and __setstate__ works like a charm for now, thank you. Instead of writing same lines of code for each model, implementing a decorator to remove ignored fields from __dict__ might be a good idea for the future.Sharpen
I second what mkubilayk desires for a future feature, it would be very much analogous to .NET's xml serialization's XmlAttributes.XmlIgnore PropertyForeandafter
W
1

This one will help others to get their task done:

Make a class like this one in a package like your custom jsonpickle package:

class SetGetState:
    def __getstate__(self):
        state = self.__dict__.copy()
        try:
            class_name = '_' + self.__class__.__name__ + '__'
            new_items = {key:value for key, value in state.items() if class_name not in key}
            return new_items
        except KeyError:
            pass
        return state

And inherit this one in the class requires no private property serialization

class Availability(jsonpickle.SetGetState):
    pass
Wight answered 23/12, 2018 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.