1

I have a number of string with json format such as '{"key1":{0}, "key2":{1}}'.

After I retrieve the json string and substitute with values. '{"key1":{0}, "key2":{1}}'.format("value1", "value2"). # KeyError: '"key1"

The problem is caused by the bracket {, and I should use {{ and }} in the string, however, it is not easy to add { to the the string because the bracket may appear in the middle part such as '{"key1":{0}, "key2":{1}, "{3}":"value3"}'

How can I format the json string?

9
  • I don't see the problem. Format like any other string and then use json.loads Commented Jul 7, 2015 at 22:39
  • @MalikBrahimi His trouble is that the format function will think it's a formatting block when it's not. Commented Jul 7, 2015 at 22:40
  • 2
    Trying to perform string substitution into the JSON string is not Pythonic and is error-prone. Build the value as a dictionary instead and use json.dumps. Commented Jul 7, 2015 at 22:40
  • @Sean where are you getting these json to-be-formatted strings from? It would seem they need to provide a better format. The only way to handle this is to recognize that {number} is not a valid dictionary because it doesn't have any :'s in it. Commented Jul 7, 2015 at 22:41
  • @Sean Are you trying to create a json string on your own? If so do what Kupiakos is saying. Commented Jul 7, 2015 at 22:43

3 Answers 3

2

Don't try to manipulate the data as an encoded string. Decode the JSON before trying to apply the formatting.

import json

json_data = '{"key1":"{0}","key2":"{1}"}'
format_args = ["value1", "value2"]

data = json.loads(json_data)
formatted_data = {key: value.format(*format_args) for key, value in data.items()}

You can then re-encode the formatted data as JSON if need be.

Sign up to request clarification or add additional context in comments.

3 Comments

Traceback (most recent call last): File "python", line 7, in <module> File "python", line 7, in <dictcomp> IndexError: tuple index out of range
I edited the answer to prevent the error above. It was missing a * to make a reference to the array for format values.
@LS Good catch, although the * has nothing to do with the reference/value distinction. It just expands the list to positional arguments. See docs.python.org/2/tutorial/….
2

If you are building these strings yourself or have control over them, have a different format be sent, or build the value as a dictionary and use json.dumps.

However, if you really need to do this, if it's guaranteed that the substitution values will be in the format {X}, then you can escape the string with this kludge:

import re
s = '{"key1":{0}, "key2":{1}}'
begin = re.compile(r'{(?!\d)')
end = re.compile(r'(?<!\d)}')
escaped = end.sub('}}', begin.sub('{{', s))
print(escaped.format(1, 2))

results in

{"key1":1, "key2":2}

Note that this is not the best solution. Considering you have control of the strings, you should be escaping them in some other way. Maybe use the % syntax instead of str.format?

1 Comment

Your regular expression will fail when json string will like : s = '{"key1":{0}, "key2":{1}, "key3":5}' So 'end' should be like following (I am not sure so I am not editing the answer) end = re.compile(r'(?<!{\d)}')
0

You can use another formatting method:

'{"key1":"%s", "key2":"%s"}' % ("value1", "value2")

Comments

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.