1

I am trying to find a way to send fields with explicit null values (as opposed to empty string value or the absence of the field itself in the request) via POST method from my UI to my Flask app backend. The latter seems to interpret null values I sent via AJAX as empty strings.

So far I'm sending my AJAX requests from the UI like this:

$.ajax({
    type: 'POST',
    url: SOME_URL,
    data: {
        foo: null
    },
    success: function() {
        // process response
    }
});

And here's what happens in Flask:

if request.form.get('foo') is None:
    # Happens only if 'foo' field was not included in the request
    return response('Got None')
elif request.form.get('foo') == '':
    # Happens for empty string or null sent as value of 'foo'
    return response('Got empty string')

Apparently, it is possible to JSONencode the POST data and subsequently decode it on the server, preserving null values as such. Is there a more elegant way to do that though? For one, using WTForms for validation would become much harder I imagine. And it would seem inconsistent to send some requests JSONencoded and others unencoded.

1 Answer 1

1

The problem is in your ajax call. By default, $.ajax is sent as application/x-www-form-urlencoded data. For example:

{
    a: 'foo',
    b: 'bar',
    c: 'baz',
    d: null,
    e: ''
}

gets transformed by jQuery into:

a=foo&b=bar&c=baz&d=&e=

jQuery seems to coerce null into an empty string, so it does literally send an empty string. There is no JSON.

To make jQuery not do that, stringify it yourself:

$.ajax({
    type: 'POST',
    url: SOME_URL,
    // Send a JSON string (NOT an object)
    data: JSON.stringify({
        foo: null
    }),
    // Tell Flask that it is a JSON string, so Flask parses as JSON
    contentType: 'application/json; charset=utf-8',  
    success: function() {
        // process response
    }
});

As a side note, you should be doing this in Python:

data = request.get_json()

if 'foo' not in data:
    # 'foo' does not exist
elif data['foo'] is None:
    # 'foo' exists and is (js) null (python) None
elif data['foo'] == '':
    # it is the empty string

Or probably something like this:

try:
    foo = data['foo']
except KeyError:
    # Handle no 'foo' key
else:
    if foo is None:
         # Handle None case
    elif isinstance(foo, str):
         # Handle string case
    else:
         logger.warn('[%s] foo is not a string or None, and instead %s', flask_session_info(), type(foo).__name__)
Sign up to request clarification or add additional context in comments.

2 Comments

I've just copy-pasted your ajax code and this way the request.form i get has no values at all. Shouldn't I be using request.get_json() instead?
To address the issue with None values in WTForms validation, one would probably need to resort to something like this: question about WTForms-JSON

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.