У меня есть следующая строка словаря:
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"cisco123\", \"name\": \"admin\"}}}"
Теперь я хочу format эту строку, чтобы заменить pwd и name динамически. Я пробовал:
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}".format('password', 'username')
Но это дает следующую ошибку:
traceback (most recent call last):
File ".\ll.py", line 4, in <module>
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}".format('password', 'username')
KeyError: '"aaaUser"
Это возможно, просто загрузив строку как dict с помощью json.loads(), а затем установив атрибуты по мере необходимости, но это не то, что я хочу. Я хочу отформатировать строку, чтобы использовать ее в других файлах / модулях.
'
Что мне здесь не хватает? Любая помощь будет оценена по достоинству.
Почему бы не использовать regex.replace?
если вы собираетесь использовать свою строку с format, вам придется удвоить все остальные фигурные скобки. На самом деле не удобно. Обман, который я связал, имеет ту же проблему)
здесь происходит то, что "{\"aaaUser\" сбивает с толку str.format, который видит это как {aaaUser} и ожидает, что какой-то параметр будет называться aaaUser в своих аргументах ...
Строго говоря, дубликат применим, но здесь это вряд ли правильно.
замена на регулярное выражение и все это было бы не лучшим подходом в моем случае, потому что я поддерживаю эти конфигурации в общем модуле и получаю доступ к нему в разных модулях, поэтому я предпочитаю форматирование замене.
CREDENTIALS = "{{\"aaaUser\": {{\"attributes\": {{\"pwd\": \"{0}\", \"name\": \"{1}\"}}}}}}".format('password', 'username')причина лишнего {?
прочтите повторяющуюся ссылку, которую вы знаете
какая дублирующая ссылка?
вопрос был закрыт как дубликат вопросов и ответов. Это ссылка. Отказ от ответственности: я ответил на этот конкретный вопрос.






Не пытайтесь работать со строкой JSON напрямую; декодировать его, обновить структура данных и перекодировать его:
# Use single quotes instead of escaping all the double quotes
CREDENTIALS = '{"aaaUser": {"attributes": {"pwd": "cisco123", "name": "admin"}}}'
d = json.loads(CREDENTIALS)
attributes = d["aaaUser"]["attributes"]
attributes["name"] = username
attributes["pwd"] = password
CREDENTIALS = json.dumps(d)
При форматировании строки вам нужно будет изменить строку, чтобы она выглядела как
CREDENTIALS = '{{"aaaUser": {{"attributes": {{"pwd": "{0}", "name": "{1}"}}}}}}'
удвоение всех скобок, чтобы метод format не принял их за заполнители.
Однако форматирование также означает, что пароль необходимо предварительно экранировать, если он содержит что-либо, что может быть ошибочно принято за синтаксис JSON, например двойные кавычки.
# This produces invalid JSON
NEW_CREDENTIALS = CREDENTIALS.format('new"password', 'bob')
# This produces valid JSON
NEW_CREDENTIALS = CREDENTIALS.format('new\\"password', 'bob')
Гораздо проще и безопаснее просто декодировать и перекодировать.
Как я уже упоминал, я знаю этот подход к загрузке, а затем сбросу, но я не понимаю, почему просто форматирование строки JSON не работает, потому что, в конце концов, это только строка, и она должна быть отформатирована так же, как и другие обычные струны.
Спасибо за ответ и правильный путь. +1 и принимаю.
str.format имеет дело с текстом, заключенным в фигурные скобки {}. Здесь переменная CREDENTIALS имеет начальную букву в виде фигурных скобок {, которая следует правилу str.format, чтобы заменить ее текст и найти сразу закрывающие фигурные скобки, поскольку она не находит их, а вместо этого получает другие открывающие фигурные скобки '{', поэтому она выдает ошибку.
The string on which this method is called can contain literal text or replacement fields delimited by braces {}
Теперь, чтобы избежать фигурных скобок и заменить только те отступы, которые можно сделать, если они заключены дважды, например
'{{ Hey Escape }} {0}'.format(12) # O/P '{ Hey Escape } 12'
Если вы избежите родительского и дедушечного {}, тогда это сработает.
Пример:
'{{Escape Me {n} }}'.format(n='Yes') # {Escape Me Yes}
Итак, следуя правилу str.format, я избегаю родительского текста, заключенного в фигурные скобки, добавляя одну дополнительную фигурную скобку, чтобы избежать его.
"{{\"aaaUser\": {{\"attributes\": {{\"pwd\": \"{0}\", \"name\": \"{1}\"}}}}}}".format('password', 'username')
#O/P '{"aaaUser": {"attributes": {"pwd": "password", "name": "username"}}}'
Теперь перейдем к форматированию строк, чтобы заставить его работать. Есть другой способ сделать это. Однако это не рекомендуется в вашем случае, так как вам нужно убедиться, что проблема всегда имеет формат, который вы упомянули, и никогда не связываться с другими, иначе результат может резко измениться.
Итак, решение, которому я следую, заключается в использовании замены строки для преобразования формата из {0} в %(0)s, чтобы форматирование строк работало без каких-либо проблем и никогда не заботилось о фигурных скобках.
'Hello %(0)s' % {'0': 'World'} # Hello World
Итак, здесь я использую re.sub для замены всех вхождений
def myReplace(obj):
found = obj.group(0)
if found:
found = found.replace('{', '%(')
found = found.replace('}', ')s')
return found
CREDENTIALS = re.sub('\{\d{1}\}', myReplace, "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}"% {'0': 'password', '1': 'username'}
print CREDENTIALS # It should print desirable result
Спасибо за ответ. +1
Почему бы не использовать
json.loads, обновить полученныйdict, а затем использоватьjson.dumpsдля получения обновленной строки? Это намного проще, чем убрать все фигурные скобки в строке, чтобы сделать ее совместимой сformat.