Форматная строка словаря

У меня есть следующая строка словаря:

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(), а затем установив атрибуты по мере необходимости, но это не то, что я хочу. Я хочу отформатировать строку, чтобы использовать ее в других файлах / модулях. '

Что мне здесь не хватает? Любая помощь будет оценена по достоинству.

Почему бы не использовать json.loads, обновить полученный dict, а затем использовать json.dumps для получения обновленной строки? Это намного проще, чем убрать все фигурные скобки в строке, чтобы сделать ее совместимой с format.

chepner 12.06.2018 17:33

Почему бы не использовать regex.replace?

emsimpson92 12.06.2018 17:33

если вы собираетесь использовать свою строку с format, вам придется удвоить все остальные фигурные скобки. На самом деле не удобно. Обман, который я связал, имеет ту же проблему)

Jean-François Fabre 12.06.2018 17:33

здесь происходит то, что "{\"aaaUser\" сбивает с толку str.format, который видит это как {aaaUser} и ожидает, что какой-то параметр будет называться aaaUser в своих аргументах ...

Jean-François Fabre 12.06.2018 17:35

Строго говоря, дубликат применим, но здесь это вряд ли правильно.

chepner 12.06.2018 17:36

замена на регулярное выражение и все это было бы не лучшим подходом в моем случае, потому что я поддерживаю эти конфигурации в общем модуле и получаю доступ к нему в разных модулях, поэтому я предпочитаю форматирование замене.

Kaushal28 12.06.2018 17:43
stackoverflow.com/questions/5466451/… это должно быть полезно: CREDENTIALS = "{{\"aaaUser\": {{\"attributes\": {{\"pwd\": \"{0}\", \"name\": \"{1}\"}}}}}}".format('password', 'username')
Ghariani Mohamed 12.06.2018 17:44

причина лишнего {?

Kaushal28 12.06.2018 17:46

прочтите повторяющуюся ссылку, которую вы знаете

Jean-François Fabre 12.06.2018 17:46

какая дублирующая ссылка?

Kaushal28 12.06.2018 17:46

вопрос был закрыт как дубликат вопросов и ответов. Это ссылка. Отказ от ответственности: я ответил на этот конкретный вопрос.

Jean-François Fabre 12.06.2018 17:50
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
11
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Не пытайтесь работать со строкой 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 не работает, потому что, в конце концов, это только строка, и она должна быть отформатирована так же, как и другие обычные струны.

Kaushal28 12.06.2018 17:41

Спасибо за ответ и правильный путь. +1 и принимаю.

Kaushal28 13.06.2018 16:42

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

Kaushal28 13.06.2018 16:41

Другие вопросы по теме