Преобразование строки с целым нулем в json - PullRequest
0 голосов
/ 14 февраля 2019

Я преобразую строку в json-объект, используя json -библиотеку:

a = '{"index":1}'
import json
json.loads(a)
{'index': 1}

Однако, если я вместо этого изменю строку a, чтобы она содержала ведущий 0, она разбивается:

a = '{"index":01}'
import json
json.loads(a)
>>> JSONDecodeError: Expecting ',' delimiter

Я полагаю, что это связано с тем фактом, что это недопустимый JSON, если целое число начинается с начального нуля, как описано в этом потоке .

Есть ли способ исправить это?Если нет, то я думаю, что лучший способ - сначала удалить все лидирующие нули с помощью регулярного выражения из строки, а затем преобразовать в json?

Ответы [ 3 ]

0 голосов
/ 14 февраля 2019

Как преобразовать строку int JSON в реальное int с помощью json.loads Пожалуйста, см. Пост выше. Вам нужно использовать собственную версию декодера.

Более подробную информацию можно найти здесь,в github https://github.com/simplejson/simplejson/blob/master/index.rst

c = '{"value": 02}'
value= json.loads(json.dumps(c))
print(value)

Кажется, это работает .. Странно

> >>> c = '{"value": 02}'
> >>> import json
> >>> value= json.loads(json.dumps(c))
> >>> print(value) {"value": 02}
> >>> c = '{"value": 0002}'
> >>> value= json.loads(json.dumps(c))
> >>> print(value) {"value": 0002}

Как @Dunes, указал, что нагрузки производит строку как результат, который не являетсяправильное решение.Однако

DEMJSON, похоже, правильно его декодирует.https://pypi.org/project/demjson/ - альтернативный способ

>>> c = '{"value": 02}'
>>> import demjson
>>> demjson.decode(c)
{'value': 2}
0 голосов
/ 14 февраля 2019

Недопустимый начальный 0 в числовом литерале в JSON, если только числовой литерал не является только символом 0 или начинается с 0..Модуль Python json довольно строг, поскольку он не будет принимать такие числовые литералы.Частично потому, что ведущий 0 иногда используется для обозначения восьмеричной записи, а не десятичной записи.Десериализация таких чисел может привести к непреднамеренным ошибкам программирования.То есть, 010 должен быть разобран как число 8 (в восьмеричной записи) или как 10 (в десятичной записи).

Вы можете создать декодер, который будет делать то, что вы хотите, новам нужно будет взломать модуль json или переписать большую часть его внутренних компонентов.В любом случае вы увидите снижение производительности, поскольку вы больше не будете использовать реализацию модуля на языке C.

Ниже приведена реализация, которая может декодировать JSON, который содержит числа с любым количеством ведущих нулей.

import json
import re
import threading

# a more lenient number regex (modified from json.scanner.NUMBER_RE)
NUMBER_RE = re.compile(
    r'(-?(?:\d*))(\.\d+)?([eE][-+]?\d+)?',
    (re.VERBOSE | re.MULTILINE | re.DOTALL))


# we are going to be messing with the internals of `json.scanner`. As such we
# want to return it to its initial state when we're done with it, but we need to
# do so in a thread safe way.
_LOCK = threading.Lock()
def thread_safe_py_make_scanner(context, *, number_re=json.scanner.NUMBER_RE):
    with _LOCK:
        original_number_re = json.scanner.NUMBER_RE
        try:
            json.scanner.NUMBER_RE = number_re
            return json.scanner._original_py_make_scanner(context)
        finally:
            json.scanner.NUMBER_RE = original_number_re

json.scanner._original_py_make_scanner = json.scanner.py_make_scanner
json.scanner.py_make_scanner = thread_safe_py_make_scanner


class MyJsonDecoder(json.JSONDecoder):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # overwrite the stricter scan_once implementation
        self.scan_once = json.scanner.py_make_scanner(self, number_re=NUMBER_RE)


d = MyJsonDecoder()
n = d.decode('010')
assert n == 10

json.loads('010') # check the normal route still raise an error

Я бы подчеркнул, что вы не должны полагаться на это как на правильное решение.Скорее, это быстрый взлом, чтобы помочь вам декодировать искаженный JSON, который почти, но не совсем корректен.Это полезно, если воссоздание JSON в правильной форме по какой-то причине невозможно.

0 голосов
/ 14 февраля 2019

Во-первых, использование регулярных выражений в JSON - это зло, почти такое же зло, как и убийство котенка.

Если вы хотите представить 01 в качестве допустимого значения JSON, рассмотрите возможность использования этой структуры:

a = '{"index" : "01"}'
import json
json.loads(a)

Если вам нужно, чтобы строковый литерал 01 вел себя как число, рассмотрите просто приведение его к целому числу в вашем скрипте Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...