Python SimpleCookie и JSON Value

Я столкнулся с некоторыми проблемами, используя Python SimpleCookie при использовании строки JSON в качестве значения.

In [1]: from http.cookies import SimpleCookie

In [2]: cookie = SimpleCookie('x=1; json={"myVal":1}; y=2')

In [3]: cookie.keys()
Out[3]: dict_keys(['x'])

In [4]: cookie = SimpleCookie('x=1; y=2')

In [5]: cookie.keys()
Out[5]: dict_keys(['y', 'x'])

Отсутствует не только строка JSON, но и все последующие значения. Мне интересно, если это ошибка, связанная с Python, так как все символы должны быть в порядке, чтобы быть использованы в cookie?

2 ответа

Решение

В настоящее время вы пытаетесь использовать объект в качестве значения, а не строковое представление JSON этого объекта. Вам нужно экранировать строку JSON в строке аргумента следующим образом:

>>> from http.cookies import SimpleCookie
>>> cookie = SimpleCookie(r'x=1; json="{\"myVal\":1}"; y=2')
                        # ^ note raw string    ^ and single backslashes
>>> cookie.keys()
dict_keys(['json', 'x', 'y'])

Кажется странным, что искаженная струна тихо поглощается, насколько это возможно, а остальная часть рвется; Я бы ожидал ValueError или что-то для вашего ввода. Синтаксический анализатор просто останавливается и возвращает результат до сих пор, когда у него заканчиваются вещи, которые соответствуют регулярному выражению.


Учитывая ответ Мариуса, который, кажется, работает на 3.3.2, но не работает в 3.5.2 (и, на мой взгляд, не похоже, что он должен работать где-либо; неявный импорт пакетов JSON?!) Я начал искать, когда это изменило. Используя этот скрипт:

from http.cookies import SimpleCookie
import json
from sys import version

print(version)

cookie1 = SimpleCookie('x=1; json=json.dumps({"myVal":1}); y=2')
print('Marius  ', cookie1.keys(), repr(cookie1.get('json')), sep='\t')

cookie2 = SimpleCookie(r'x=1; json="{\"myVal\":1}"; y=2')
print('Jonathan', cookie2.keys(), repr(cookie2.get('json')), sep='\t')

cookie3 = SimpleCookie('x=1; json={"myVal":1}; y=2')
print('Bernhard', cookie3.keys(), repr(cookie3.get('json')), sep='\t')

а также pyenv на Mac OS X дает следующие результаты для 3.3:

3.3.0 (default, Jul  7 2016, 10:47:41)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['x', 'y', 'json'])   <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['x', 'y', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['x', 'y', 'json'])   <Morsel: json='{'>

3.3.1 (default, Jul  7 2016, 10:53:06)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['json', 'x', 'y'])   <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['json', 'x', 'y'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['json', 'x', 'y'])   <Morsel: json='{'>

3.3.2 (default, Jul  6 2016, 22:02:23)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['json', 'y', 'x'])   <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['json', 'y', 'x'])   <Morsel: json='{'>

# ...loses 'json'

3.3.3 (default, Jul  7 2016, 10:57:02)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['x', 'y'])   None
Jonathan    dict_keys(['x', 'y', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['x', 'y'])   None

3.3.4 (default, Jul  7 2016, 10:59:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['y', 'x'])   None
Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['y', 'x'])   None

3.3.5 (default, Jul  7 2016, 11:01:45)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['y', 'x'])   None
Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['y', 'x'])   None

# ...and now 'y'!

3.3.6 (default, Jul  7 2016, 11:03:40)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['x'])    None
Jonathan    dict_keys(['json', 'x', 'y'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['x'])    None

Оттуда это кажется стабильным:

3.4.4 (default, Jul  7 2016, 11:13:43)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['x'])    None
Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['x'])    None

3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
Marius      dict_keys(['x'])    None
Jonathan    dict_keys(['x', 'json', 'y'])   <Morsel: json="{\"myVal\":1}">
Bernhard    dict_keys(['x'])    None

Версия начиная с 3.3.6, очевидно, была исправлением безопасности; см. этот отчет об ошибке. Это также было применено в 3.2.6, поэтому:

3.2.4 (default, Jul  7 2016, 11:05:33)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['y', 'x', 'json'])   <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['y', 'x', 'json'])   <Morsel: json='{'>

3.2.5 (default, Jul  7 2016, 11:07:15)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['y', 'x', 'json'])   <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['y', 'x', 'json'])   <Morsel: json='{'>

# ...loses 'y'?!

3.2.6 (default, Jul  7 2016, 11:09:00)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
Marius      dict_keys(['x', 'json'])    <Morsel: json='json.dumps({'>
Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
Bernhard    dict_keys(['x', 'json'])    <Morsel: json='{'>

Это поведение отличается от 3.3.6 с тем же исправлением! На самом деле, он устанавливает значение json в печенье, чтобы '{', отбрасывая остальную часть этого значения и y,

Я пришел к выводу, что:

  1. моя версия более широко применима;
  2. Версия Мариуса на самом деле не поможет OP, поскольку она имеет те же ключи, что и их оригинальная версия; а также
  3. что-то странное происходило с этой функциональностью в 3.2 и 3.3!

Это включает 'json' как ключ в Python 3.3.2 и ранее:

>>> import json
>>> from http.cookies import SimpleCookie
>>> cookie = SimpleCookie('x=1; json=json.dumps({"myVal":1}); y=2')
>>> cookie.keys()
dict_keys(['y', 'x', 'json'])

Однако значение может отличаться от ожидаемого:

>>> print(cookie)
Set-Cookie: json=json.dumps({
Set-Cookie: x=1
Set-Cookie: y=2
Другие вопросы по тегам