16

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.

mkubilayk
  • 2,477
  • 3
  • 20
  • 27

2 Answers2

27

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 5
    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. – mkubilayk Aug 09 '13 at 14:11
  • 1
    I second what mkubilayk desires for a future feature, it would be very much analogous to .NET's xml serialization's [XmlAttributes.XmlIgnore Property](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributes.xmlignore(v=vs.110).aspx) – jxramos Apr 27 '17 at 22:23
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
Ahmad Asjad
  • 825
  • 1
  • 8
  • 29