schrodinger.models.json module

This is a module that extends Python’s standard builtin json module. It offers the following additional features:

exception schrodinger.models.json.JSONEncodeError

Bases: ValueError

class schrodinger.models.json.AttributableType(iterable=(), /)

Bases: list

class schrodinger.models.json.JsonableClassMixin

Bases: object

A mixin that aids in making a class Jsonable. Users must define toJsonImplementation(self) and fromJsonImplementation(cls, json_dict). For example:

class Person(JsonableClassMixin, object):

    def __init__(self, full_name, age):
        self.full_name = full_name
        self.age = age

    def toJsonImplementation(self):
        return {'full_name':self.full_name,
                'age':self.age}

    @classmethod
    def fromJsonImplementation(cls, json_dict):
        return cls(json_dict['full_name'], json_dict['age'])

Now dump and dumps can encode Person:

# Encode to a file
abe = Person('Abraham Lincoln', 208)
with open('abe.json', 'w') as out_file:
    json.dump(abe, out_file)

# Encode to a string
abe_json_string = json.dumps(abe)

If you want to decode the json string or file, you’ll have to use loads or load and then feed in the result to your class’ public class method fromJson():

# Loading an object from a json file
with open('abe.json', 'r') as in_file:
    abe = json.load(in_file, DataClass=Person)

# Loading an object from a json string
abe = json.loads(abe_json_string, DataClass=Person)
toJsonImplementation()

Abstract method that must be defined by all derived classes. Converts an instance of the derived class into a jsonifiable object.

Returns

A dict made up of JSON native datatypes or Jsonable objects. See the link below for a table of such types. https://docs.python.org/2/library/json.html#encoders-and-decoders

classmethod fromJsonImplementation(json_dict)

Abstract method that must be defined by all derived classes. Takes in a dictionary and constructs an instance of the derived class.

Parameters

json_dict (dict) – A dictionary loaded from a JSON string or file.

Returns

An instance of the derived class.

Return type

cls

toJson(_mark_version=True)

Create and returns a data structure made up of jsonable items.

Return type

An instance of one the classes from NATIVE_JSON_DATATYPES

classmethod fromJson(json_obj)

A factory method which constructs a new object from a given dict loaded from a json string or file.

Parameters

json_obj (dict) – A json-loaded dictionary to create an object from.

Returns

An instance of this class.

Return type

cls

get_version()

Method to get the version of a particular object. Defaults to the current version of mmshare. This class can be overridden for custom versioning behavior.

schrodinger.models.json.adapter(version)

This function is a decorator used to define an adapter function that takes in a json_obj from an older version of a JsonableClassMixin and returns it modified such that it can be read in by the version of the class specified by the version argument (typically the current version at the time the adapter is written).

As a example, imagine we define a simple class:

class Person:
    # mmshare version: 40000
    def __init__(self, full_name):
        self.full_name = full_name

If, in mmshare version 41000, we split full_name into attributes first_name and last_name, we could define an adapter like so:

class Person:
    # mmshare version: 41000
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @json.adapter(version=41000)
    def _JsonAdapter(self, json_dict):
        full_name = json_dict.pop(full_name)
        fname, lname = full_name.split(' ')
        json_dict['first_name'] = fname
        json_dict['last_name'] = lname
        return json_dict

Note

An adapter function only needs to bring the json_dict up-to-date with the class at the time that the adapter is written. The next time the class is changed in a way that breaks json decoding, a new adapter function should be added to the class that takes in the previous adapter’s output and makes it compatible with the current class. In this way the json framework can decode any older version by automatically passing it through the appropriate chain of adapter functions.

Parameters

version (int, str, or list of str or ints) – The data version to which an older json_dict will be adapted (typically the current version when the adapter is writte).

Raises

TypeError – if version is not an int, str, or list

schrodinger.models.json.get_json_version_from_file(json_fh)

Get the version information from a json file serialized from JsonableClassMixin objects. Returns None if no version information is found.

schrodinger.models.json.get_json_version_from_string(json_str)

Get the version information from a json string serialized from JsonableClassMixin objects. Returns None if no version information is found.

schrodinger.models.json.decode(obj, DataClass=None, serializer=None)

Decode the obj from a json structure to the original object that encoded it. This is done using the following methods in order of priority:

  1. Detecting whether the jsoned object originally implemented JsonableClassMixin. If it was, decode it into a normal json object and retrieve the version number.

  2. Using DataClass if it’s a typing annotation generic (e.g.

    typing.List, typing.Tuple, etc)

  3. Using the supplied serializer

  4. Inferring a serializer using DataClass

schrodinger.models.json.dumps(obj, serializer=None, **kwargs)

A wrapper that automatically encodes objects derived from JsonableClassMixin.

Parameters

serializer (jsonable.AbstractJsonSerializer) – A custom serializer to use for serializing the object. This should not be used at the same time as the DataClass argument.

If obj does not subclass JsonableClassMixin, then this function will behave exactly like the builtin json.dumps.

schrodinger.models.json.dump(obj, fp, serializer=None, **kwargs)

A wrapper that automatically encodes objects derived from JsonableClassMixin.

Parameters

serializer (jsonable.AbstractJsonSerializer) – A custom serializer to use for serializing the object. This should not be used at the same time as the DataClass argument.

If obj does not subclass JsonableClassMixin, then this function will behave exactly like the builtin json.dump.

schrodinger.models.json.loads(json_str, DataClass=None, serializer=None, **kwargs)

A wrapper that automatically decodes json strings serialized from JsonableClassMixin objects.

param DataClass

The class of the object that was serialized into json_str. The class must either be in JSONABLE_DATATYPES or a type that’s been registered in schrodinger.models.jsoable.

Parameters

serializer (jsonable.AbstractJsonSerializer) – A custom serializer to use for deserializing the string. This should not be used at the same time as the DataClass argument.

If the json string was not encoded JsonableClassMixin object, this function will behave exactly like the builtin json.loads.

schrodinger.models.json.load(fp, DataClass=None, serializer=None, **kwargs)

A wrapper that automatically decodes json files serialized from JsonableClassMixin objects.

param DataClass

The class of the object that was serialized into fp. The class must either be in JSONABLE_DATATYPES or a type that’s been registered in schrodinger.models.jsonable.

Parameters

serializer (jsonable.AbstractJsonSerializer) – A custom serializer to use for deserializing the file. This should not be used at the same time as the DataClass argument.

If the json file was not encoded JsonableClassMixin object, this function will behave exactly like the builtin json.load.