【问题标题】:Hacking JavaScript Array Into JSON With Python使用 Python 将 JavaScript 数组转换为 JSON
【发布时间】:2010-11-11 18:40:48
【问题描述】:

我正在从远程站点获取一个 .js 文件,该文件包含我想使用我的 Google App Engine 站点上的 simplejson 库以 JSON 格式处理的数据。 .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 表示法?

【问题讨论】:

    标签: javascript python json


    【解决方案1】:

    使用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"}}]
    

    您还可以将分配添加到语法本身。鉴于已经有现成的解析器,你应该更好地使用它们。

    【讨论】:

    • 感谢您对 pyparsing 的引用...这将在未来派上用场。不确定要接受哪个答案。
    • 我遗漏的细节之一是数组中的一个字段是使 yaml 窒息 (:, ', ") 的字符的野兽。我需要抑制它们,我认为这个解决方案会让我做到这一点。
    • 这很不错,尽管它不处理 true、false 和 null 关键字或 Unicode 转义(不确定它们是否会弹出)。
    • 扩展允许值的范围并添加一个带有类似内置函数的小字典并不难。我主要写了这个答案来宣传 PyParsing:)
    【解决方案2】:

    在大多数情况下,我会使用 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。

    【讨论】:

    • 酷,我不知道 yaml 库。我现在在其中一个领域遇到了一些困难......它有一些我必须压制的虚假字符。考虑到这个问题,我可能需要使用 pyparsing 解决方案。
    • 格雷格,你有什么问题?
    • 基本上,我有一些带有斜线、转义、冒号和撇号的值,例如 'oranges:with:1,ripe:\"yes\"',这使得扫描文本变得困难解析。
    【解决方案3】:

    如果您知道这就是它的外观,您可以执行一个正则表达式来查找以冒号结尾的不带引号的空格分隔文本并用引号括起来。

    不过,我总是担心像这样的正则表达式的意外输入。你怎么知道远程源不会改变你得到的东西?

    【讨论】:

    • 我不知道它是否/何时发生变化......这是一个脆弱的解决方案,可以肯定的是,当它发生变化时我会有错误处理来报告。但这只是一个爱好应用程序。 :)
    【解决方案4】:

    您可以创建一个包含 Javascript 脚本的中间页面,该脚本仅加载远程页面并将其转储为 JSON。然后 Python 可以向你的中间页面发出请求并得到漂亮的 JSON。

    【讨论】:

    • 我希望将其保留为一跳,因为我将使用多个文件来执行此操作......所以现在将每个额外的一跳至少乘以六。
    • 您可以将所有请求捆绑到一个对中间页面的请求中,因此这实际上只会增加一跳。
    猜你喜欢
    • 2014-06-21
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    相关资源
    最近更新 更多