Взлом массива JavaScript в JSON с помощью Python - PullRequest
4 голосов
/ 17 июля 2009

Я получаю файл .js с удаленного сайта, который содержит данные, которые я хочу обработать как JSON, используя библиотеку simplejson на моем сайте Google App Engine. Файл .js выглядит так:

var txns = [
    { apples: '100', oranges: '20', type: 'SELL'}, 
    { apples: '200', oranges: '10', type: 'BUY'}]

У меня нет контроля над форматом этого файла. Сначала я просто взломал его, отрубив бит "var txns = " в строке, а затем выполнил серию .replace(old, new, [count]) в строке, пока она не стала похожа на стандартный JSON:

cleanJSON = malformedJSON.replace("'", '"').replace('apples:', '"apples":').replace('oranges:', '"oranges":').replace('type:', '"type":').replace('{', '{"transaction":{').replace('}', '}}')

Так что теперь это выглядит так:

[{ "transaction" : { "apples": "100", "oranges": "20", "type": "SELL"} }, 
 { "transaction" : { "apples": "200", "oranges": "10", "type": "BUY"} }]

Как бы вы решили эту проблему форматирования? Есть ли известный способ (библиотека, скрипт) для форматирования массива JavaScript в нотации JSON?

Ответы [ 4 ]

5 голосов
/ 17 июля 2009

Не так уж сложно написать собственный маленький парсор для этого, используя PyParsing .

import json
from pyparsing import *

data = """var txns = [
   { apples: '100', oranges: '20', type: 'SELL'}, 
   { apples: '200', oranges: '10', type: 'BUY'}]"""


def js_grammar():
    key = Word(alphas).setResultsName("key")
    value = QuotedString("'").setResultsName("value")
    pair = Group(key + Literal(":").suppress() + value)
    object_ = nestedExpr("{", "}", delimitedList(pair, ","))
    array = nestedExpr("[", "]", delimitedList(object_, ","))
    return array + StringEnd()

JS_GRAMMAR = js_grammar()

def parse(js):
    return JS_GRAMMAR.parseString(js[len("var txns = "):])[0]

def to_dict(object_):
    return dict((p.key, p.value) for p in object_)

result = [
    {"transaction": to_dict(object_)}
    for object_ in parse(data)]
print json.dumps(result)

Это будет печатать

[{"transaction": {"type": "SELL", "apples": "100", "oranges": "20"}},
 {"transaction": {"type": "BUY", "apples": "200", "oranges": "10"}}]

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

4 голосов
/ 17 июля 2009

Я бы использовал парсер yaml как лучший в большинстве подобных вещей. Он поставляется с GAE, а также используется для файлов конфигурации. Json - это подмножество yaml.

Все, что вам нужно сделать, это избавиться от "var txns =", тогда yaml должен сделать все остальное.

import yaml

string = """[{ apples: '100', oranges: '20', type: 'SELL'}, 
             { apples: '200', oranges: '10', type: 'BUY'}]"""

list = yaml.load(string)

print list

Это дает вам.

[{'type': 'SELL', 'apples': '100', 'oranges': '20'},
 {'type': 'BUY', 'apples': '200', 'oranges': '10'}]

После загрузки вы всегда можете сбросить его обратно как json.

0 голосов
/ 17 июля 2009

Вы можете создать промежуточную страницу, содержащую сценарий Javascript, который просто загружает удаленный и выгружает его в JSON. Затем Python может отправлять запросы на вашу промежуточную страницу и получать хороший JSON.

0 голосов
/ 17 июля 2009

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

Меня всегда беспокоит неожиданный ввод с таким регулярным выражением. Откуда вы знаете, что удаленный источник не изменит то, что вы получите?

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