Search code examples
pythonming

Ming ODM MappedClass json conversion


How do I convert a MappedClass object to JSON?

json.dumps({"data": mappedClassObject}, indent=True)

Above code raises error that MappedClass object is not JSON serializable.

Is there any utility similar to BSON's json_util to convert MappedClass to JSON? or Do I have to write a encoder as mentioned in TypeError: ObjectId('') is not JSON serializable

Am using python 2.7


Solution

  • As of now, I have created a encoder for my use. This is hacky and if there is a better alternate, I will consider it.

    # MappedClass from Ming is not JSON serializable and we do not have utilities like json_util (for BSON) to convert
    # MappedClass object to JSON. Below encoder is created for this requirement.
    # Usage: MappedClassJSONEncoder().encode(data)
    class MappedClassJSONEncoder(JSONEncoder):
        """
        Returns a MappedClass object JSON representation.
        """
    
        def _get_document_properties(self, klass):
            """
            Returns the declared properties of the MappedClass's child class which represents Mongo Document
            Includes only the user declared properties such as tenantId, _id etc
            :param klass:
            :return:
            """
            return [k for k in dir(klass) if k not in dir(MappedClass)]
    
        def _get_attr_json_value(self, attr):
            if isinstance(attr, bson.objectid.ObjectId):
                return str(attr)
            elif isinstance(attr, datetime.datetime):
                return attr.isoformat()
            elif isinstance(attr, dict):
                dict_data = {}
                for member in attr:
                    dict_data.update({member: self._get_attr_json_value(attr[member])})
                return dict_data
            else:
                return attr
    
        def default(self, o):
            mapped_class_attributes = self._get_document_properties(type(o))
            attributes_data = {}
            for attr_name in mapped_class_attributes:
                attr = o.__getattribute__(attr_name)
                attributes_data.update({attr_name: self._get_attr_json_value(attr)})
            return attributes_data