简体   繁体   中英

Don't quote some strings with using json.dumps

I'm working on a Django wrapper for jqGrid (yes, another one, the existing ones don't fit my needs). In my wrapper I'm generating the Javascript code that initializes the grid. This code looks like this:

$('#my-grid').jqGrid({
    "option1": 12,
    "option2": "option",
    "eventHandler": handlerFunction
});

Since I'm generating this code in Python, I've created a dictionary like so:

options = {"option1": 12, "option2": "option", "eventHandler": "handlerFunction"}

I then use json.dumps like so:

js_code = "${'#my-grid').jqGrid(%s);" % json.dumps(options)

The problem is that json.dumps puts quotes around "handlerFunction" , which is not what I want. I want handlerFunction to be unquoted, so that it is evaluated as a function in JavaScript, and not as a string.

How can I tell json.dumps not to quote some of the strings?

I was hoping a custom JsonEncoder would do the trick, but no - objects returned from encoders pass through the normal encoding sequence, so strings are quoted.

So I had to do something else:

First I defined the following function:

def function(name):
    return '@@' + name + '@@'

Then I created a JSON encoding function, instead of json.dumps:

def my_dumps(obj, *args, **kwargs):
    s = json.dumps(obj, *args, **kwargs)
    s = s.replace('"@@', '')
    s = s.replace('@@"', '')
    return s

Now I can create my to-be-jsoned dictionary like this: {'event': function(handler)} and it will be encoded properly.

Not pretty, but it works.

That won't work. The solution is not to mix logic in Python and JavaScript. Here is one way: move all your JavaScript to template and pass only data to it like this:

def some_view(...):
    grid_options = {
        "option1": 12,
        "option2": "option",
    }
    return render(request, {'grid_options': json.dumps(grid_options)})

In view:

var gridOptions = {{ grid_options }};

$('#my-grid').jqGrid($.extend(gridOptions, {
    "eventHandler": handlerFunction
});

json.dumps can not provide such function, neither does Python, because it's not a valid json string. You should try to unquote it in JS.

In addition to @zmbq's answer: my_dumps wraps the keys for you.

key_wrap_seq = '@@'

def wrap_key(name):
    return key_wrap_seq + name + key_wrap_seq

def wrap_obj_keys(obj):
    if type(obj) is dict:
        return {wrap_key(k): wrap_obj_keys(obj[k]) for k in obj}
    elif type(obj) is list:
        return [wrap_obj_keys(x) for x in obj]
    else:
        return obj

def my_dumps(obj, *args, **kwargs):
    obj_wrapped = wrap_obj_keys(obj)
    s = json.dumps(obj_wrapped, *args, **kwargs)
    s = s.replace('"'+key_wrap_seq, '')
    s = s.replace(key_wrap_seq+'"', '')
    return s

Result:

>>> obj = {"name": "john", "age": 22}
>>> my_dumps(obj)
... '{name: "john", age: 22}'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM