Python json dumps single backslash

I need a JSON HTTP response to be as follows:

{date: "\/Date[1411084800000]\/"}

I have a python dict event with a property date such that

event['date'] = "\/Date[1411084800000]\/"

Now when I return the dict using flask I am passing it through jsonify. It is unfortunately escaping the single backslash and adding a double backslash to the JSON. \\/Date["1411084800000"]\\/. I need to get rid of the double back slash, how should I do this?

You are wondering why I would ever want to return a crazy result like this? Well that is how Kendo Scheduler expects date objects. See //demos.telerik.com/kendo-ui/scheduler/index

Any help would be appreciated. Thanks!

asked Sep 17, 2014 at 20:39

JakobovskiJakobovski

2,9351 gold badge28 silver badges37 bronze badges

6

You are seeing an escaped forward slash. The JSON standard allows any character to be escaped, and the forward slash can be escaped by preceding it with a backward slash. See the Strings section of RFC 7159.

So \/ is an just an escaped representation for the value /:

>>> import json
>>> print json.loads[r'{"date": "\/Date[1411084800000]\/"}']
{u'date': u'/Date[1411084800000]/'}

Note how the \/ is decoded to / in the output. This escaping is entirely optional.

Your browser does the same thing; when any compliant JSON value which includes strings containing \/ sequences is being parsed, the resulting string values containg just / forward slashes. When the Kendo JSONP response [which does use \/ in strings] is received, the browser produces the exact same result as a JSONP response with the forward slashes left un-escaped.

Just provide the value in Python with the forward slashes. json.dumps[] will not escape the forward slash [it doesn't have to escape it], and your browser and any other JSON compliant parser will produce the exact same value:

>>> print json.dumps[{'date': '/Date[1411084800000]/'}]
{"date": "/Date[1411084800000]/"}

answered Sep 18, 2014 at 9:21

Martijn PietersMartijn Pieters

983k272 gold badges3871 silver badges3232 bronze badges

0

While Martijn is absolutely correct, he does include a caveat about the far end being compliant. If it isn't, like JustGiving, then you might find the following a useful starting point:

class DateJSONEncoder[json.JSONEncoder]:
    def default[self, o]:
        if isinstance[o, datetime.date]:
            javascript_date = int[o.strftime["%s"]]*1000
            return r'\/Date[{0}+0000]\/'.format[javascript_date]
        return JSONEncoder.default[self, o]

    def encode[self, o]:
        encoded = super[DateJSONEncoder, self].encode[o]
        encoded = encoded.replace[r"\\/", r"\/"].replace[r"]\\/", r"]\/"]
        return encoded

answered Apr 7, 2016 at 11:23

Not the answer you're looking for? Browse other questions tagged python json kendo-ui flask or ask your own question.

I am using jsonnet to write configurations for drone ci. Drone uses jsonnet to generate yaml file and use it as instruction for CI/CD.

For my needs I want to have the following output:

{ "some-field" : "${DRONE_BRANCH/\//-}" }

I tried the following jsonnet script:

{
  "some-field": "${DRONE_BRANCH/\//-}",
}

And it gave me:

{
   "some-field": "${DRONE_BRANCH///-}"
}

Then I tried:

{
   "some-field": "${DRONE_BRANCH/\\//-}"
}

It gave me:

{
   "some-field": "${DRONE_BRANCH/\\//-}"
}

I did not find a way to achieve what I want. Seems to me it's currently impossible.

P.S. I am using the latest version of jsonnet

$ jsonnet -v
Jsonnet commandline interpreter v0.13.0

alikhil, Raiondesu, prokop7, kevinkhanda, nickaleks, IvanovaChristina, Vsnegovik, gadhagod, and gaurav517 reacted with thumbs up emojiRaiondesu, kevinkhanda, Vsnegovik, and gaurav517 reacted with rocket emoji

+10 for this. How come single slashes are not allowed in a JSON?
This is ridiculous.

The thing is that in JSON "/" and "\/" are equivalent, i.e. they describe the same sequence of characters [i.e. a single character U+002F]. If I'm interpreting the JSON specification correctly, every compliant implementation should treat them the same per RFC 7159 8.3 String Comparison.

Similarly JSON strings "${DRONE_BRANCH/\//-}" and "${DRONE_BRANCH///-}" refer to exactly the same sequence of characters ${DRONE_BRANCH///-}. If you want a JSON string which denotes a string with a backslash there [e.g. because you feed it to a script which requires an escaped slash there], you should actually escape the backslash. So if you want a JSON meaning ${DRONE_BRANCH/\//-}, the right JSON is "${DRONE_BRANCH/\\//-}.

Python agrees btw:

>>> json.dumps[json.loads['"${DRONE_BRANCH/\\//-}"']] # double escaping
'"${DRONE_BRANCH///-}"'
>>> x = '"${DRONE_BRANCH/\\//-}"' # double escaping
>>> print[x]
"${DRONE_BRANCH/\//-}"
>>> print[json.loads[x]]
${DRONE_BRANCH///-}
>>> x = '"${DRONE_BRANCH/\\\\//-}"' # double escaping
>>> print[x]
"${DRONE_BRANCH/\\//-}"
>>> print[json.loads[x]]
${DRONE_BRANCH/\//-}

Escaping / is unnecessary, so Jsonnet doesn't put it there. Jsonnet generally goes for minimally escaped strings in the output.

Please let me know if that answers your question.

@sbarzowski, though it's a comprehensive answer, I suggest you pay more attention when reading the question.

Then I tried:

{
  "some-field": "${DRONE_BRANCH/\\//-}"
}

It gave me:

{
  "some-field": "${DRONE_BRANCH/\\//-}"
}

In other words, escaping the escaping backslash just produces two backslashes.

Therefore, the last bit of "example output" you've provided is not how jsonnet handles this.

Instead, it actually produces

>>> print[x]
"${DRONE_BRANCH/\\//-}"
>>> print[json.loads[x]]
${DRONE_BRANCH/\\//-}

Instead, it actually produces

Did you actually run it in Python? This was directly copy&pasted from Python shell. Here you can see it yourself: //www.onlinegdb.com/S1g978ilH.

In other words, escaping the escaping backslash just produces two backslashes.

Yes, because it also needs to be escaped in the output JSON. I'm arguing that it is the correct behavior. And that trying to get JSON output { "some-field" : "${DRONE_BRANCH/\//-}" } specifically and not { "some-field" : "${DRONE_BRANCH///-}" } is probably a wrong goal, because these two are equivalent. These two JSONs mean exactly the same thing, so why would you prefer the one with unnecessary escaping?

For completeness I'll add that you can use the "raw string" mode [-S option] to do your own serialization if you really want to. Then your program must produce a string, which will be printed without any additional escaping. But as long as your output is standard JSON you shouldn't have to.

In other words if you want it to be loaded with a single backslash you need these two backslashes in JSON.

E.g.:

➜ jsonnet -e '{
   "some-field": "${DRONE_BRANCH/\\//-}"
}' | python -c 'import json; import sys; print[json.load[sys.stdin]["some-field"]]'
${DRONE_BRANCH/\//-}

With a single backslash it won't work as expected [it will be interpreted as escaped / which is just /]:

➜ cat foo.json
{ "some-field" : "${DRONE_BRANCH/\//-}" }
➜ cat foo.json | python -c 'import json; import sys; print[json.load[sys.stdin]["some-field"]]'
${DRONE_BRANCH///-}

I'm going to assume that it's all clear now after my last explanation. If it's not, feel free to reopen.

Just came here to add that in YAML, you can specify a single character string containing a backslash as either:

or

In JSON, only the latter is supported. When Jsonnet generates YAML with std.manifestYAMLDoc, it chooses to emit YAML in the second form, because implementing that is simpler, and it's equivalent. Drone CI should interpret "\\" in the way that you want.

Oh and just for completeness -- the various ways of specifying it in Jsonnet:

[
  "\\",
  '\\',
  @"\",
  @'\',
  // Note, this last one also adds a \n, see #289
  |||
    \
  |||,
]

Chủ Đề