1

Context

I have a Flask app that uses sqlalchemy to query a database and serialize the resulting sqlalchemy object. After the template is rendered, I want to pass the serialized object to /_background_process route using a jQuery callback function on keyup (see jQuery and route below).

The serialized object is passed in the callback function via an argument named callbackarg using the jinja2 "{{ ... }}" delimiter. The quotation marks are required else a SyntaxError will occur because serializedobj is a bytes object including invalid tokens like & (such as in b'\x80\x04\x95...)

Where I'm stuck

When the serialized object is retrieved via request.args.get('callbackarg') in the /_background_process route, it is of string type with bytes syntax (versus bytes type) and has lost the decode attribute. This is a problem because the argument must be a bytes object to deserialize with the loads method of sqlalchemy.ext.serializer

Some of the things I've tried

I've tried using other serializer libraries. Both flask.jsonify and json.dumps fail because one of the child objects in the sqlalchemy object "is not JSON serializable". pickle.dumps gives an identical result to dumps method of sqlalchemy.ext.serializer. The approach described in this stackoverflow link also fails because of elements that are not JSON serializable.

Summarizing the question

Is there a way to deserialize retrievedobj in the /_background_process route after it has been serialized and passed as a string with bytes syntax in a callback function? If there is no way, please would you weigh in on the related question I asked on November 1 link? Thanks!

jQuery in Flask template

<script type=application/javascript>
$(function() {
    $('#process_input').on('keyup', function() {
    $.getJSON('/_background_process', {
        userinput: $('input[name="userinput"]').val(),
        callbackarg: {{ serializedobj }}
    }, function(data) {
        $("#result").text(data.result);
    });
    return false;
    });
});

App route

@app.route('/_background_process')
def _background_process():
    retrievedobj = request.args.get('callbackarg')
    ...

Footnote This is a different question than the one I asked Nov 1 link because, whereas that question was about passing an object of type sqlalchemy, this question is strictly about passing a serialized object.

Bryton Beesley
  • 167
  • 2
  • 12
  • 1
    You really should stop and think for a moment at this point. First off, reading https://docs.sqlalchemy.org/en/latest/core/serializer.html it seems it isn't meant for serializing model objects. You're saying that some child object in your model object is not JSON serializable. In that case write an adapter/converter that makes it so. Don't try and use string representations of Python objects as "serialization". Also, pickle isn't safe against malicious data, so in general it might not be a good idea to accept pickled data in an endpoint as input. – Ilja Everilä Nov 17 '18 at 21:01
  • 1
    you almost certainly don't want to do this. anything coming from the browser should be treated as untrusted. https://jwt.io/ might help, but you should probably just be saving the relevant state into a database – Sam Mason Nov 17 '18 at 21:46

0 Answers0