1

I'm making a Python API get request and getting JSON results which I have captured in a string. The string is similar to a string literal containing a dictionary: {'key1': 4, 'key2': 'I\'m home'}. I need to format it to a string literal containing a proper JSON object like this: {"key1": 4, "key2": "I\'m home"}, so that I can save to a JSON file.

To achieve this, I tried using regular expressions with negative look-ahead to replace all the single quotes (except the escaped single quote) like this:

import re

#.... other codes
str = re.sub("'(!?\')", "\"", result) # result = "{'key1': 4, 'key2': 'I\'m home'}"
print (str)

But I get this output

{"key1": 4, "key2": "I"m home"}

instead of

{"key1": 4, "key2": "I\'m home"}

How do I create the regular expression, so that escaped single quotes \' are preserved and all others are replaced with double-quotes.

Amir Afianian
  • 2,679
  • 4
  • 22
  • 46
Udo E.
  • 2,665
  • 2
  • 21
  • 33
  • 1
    So you are getting JSON results that aren't JSON? – mkrieger1 Nov 01 '20 at 20:33
  • ```result = requests.get(url).json()```. I'm getting results from a Python ```requests.get()``` object method and the method is named ```json()```. But result is returned with keys in single quote, which Visual Studio code is reporting as not a proper json when I copy it to a json file. – Udo E. Nov 01 '20 at 20:40
  • Does this answer your question? [HTTP requests and JSON parsing in Python](https://stackoverflow.com/questions/6386308/http-requests-and-json-parsing-in-python) – mkrieger1 Nov 01 '20 at 20:46
  • It seems you do not have to do anything, `requests.get(url).json()` already decodes the JSON and returns a Python data structure. – mkrieger1 Nov 01 '20 at 20:47
  • 1
    You can *encode* it back to a JSON string by using `import json; json.dumps(result)`, if that's what you want. Or you can skip the decoding and return the JSON string directly, by using [`requests.get(url).raw`](https://requests.readthedocs.io/en/master/user/quickstart/#raw-response-content) instead. – mkrieger1 Nov 01 '20 at 20:49
  • @mkrieger1, I've just tried that on my machine. result is still dumped with keys in single quote. *I want keys in double quote* – Udo E. Nov 01 '20 at 21:00
  • `"{'key1': 4, 'key2': 'I\'m home'}"` does _not_ have a backslash: `\'` is simply a `'`. `"{'key1': 4, 'key2': 'I\\'m home'}"` _does_ have a backslash. Which one do you actually have? – DYZ Nov 01 '20 at 21:14
  • @DYZ it's the former. I want to keep track of the "history of manipulations" done on the data, that is the reason I'm capturing it to a string. I'm aware ```I\'m``` will display as ```I'm``` when sent to the display. But your answer gets it right in a way. I'll have to escape all backslashes before using the negative lookbehind. – Udo E. Nov 01 '20 at 21:33

1 Answers1

3

You need a negative lookbehind, not a negative lookahead ("no backslash before a quote"):

result = '''{'key1': 4, 'key2': 'I\\'m home'}'''
print(re.sub(r"(?<!\\)'", '"', result))
#{"key1": 4, "key2": "I\'m home"}
DYZ
  • 55,249
  • 10
  • 64
  • 93
  • This is not still working for me. I'm still getting ```{"key1": 4, "key2": "I"m home"}```. I just tried it on my machine. – Udo E. Nov 01 '20 at 21:06
  • Your answer gets it right in a way. I'll have to escape all backslashes before using the negative lookbehind. – Udo E. Feb 20 '22 at 15:45