递归解析 JSON

Posted

技术标签:

【中文标题】递归解析 JSON【英文标题】:Recursively parsing JSON 【发布时间】:2011-05-05 11:54:05 【问题描述】:

我有一个用 Python 创建的大型 JSON 对象,我现在需要在网页上显示信息。我的问题是它的大小;里面有嵌套的数组和对象,点处有好几层。我写了一个非常不优雅(而且有问题)的 javascript 函数来提取数据,但这对我来说似乎是一个递归问题,不幸的是我不习惯这样思考(还)。

有谁知道解析读取此类对象的好方法?我的目标是真正动态地阅读它,因为我将不得不多次这样做(并且每次对象都会不同,但结构或多或少相同)。 目标是获取这些信息并在网页上有意义地显示它。

如果我可以进一步详细说明,请告诉我。

编辑:这是对象。当我发布这篇文章时,我不在我的电脑旁,而且它相当大。我已经删除了其中可能敏感的部分。我正在使用 JSON2 将其解析为字符串以外的内容。只是大小和嵌套给我带来了问题。


    "Loop300": [
        
            "Loop310": [
                
                    "N1": 
                        "idCode": "0400", 
                        "idQual": "ZZ", 
                        "name": "REDACTED", 
                        "entIdCode": "SF"
                    , 
                    "N3": [
                        
                            "address1": "REDACTED", 
                            "address2": "REDACTED"
                        
                    ], 
                    "G61": [
                        
                            "contactFunctionCode": "CN", 
                            "commNumber": "REDACTED", 
                            "commNumQualifier": "TE", 
                            "name": "shipping"
                        
                    ], 
                    "N4": [
                        
                    ]
                
            ], 
            "L11": [], 
            "S5": 
                "stopReasonCode": "LD", 
                "stopSeqNum": "1"
            , 
            "Loop350": [
                
                    "LAD": [], 
                    "OID": 
                        "weight": "161", 
                        "poNum": "ASDF", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "THING", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "1", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "104", 
                        "poNum": "ZXMO", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "STUFF", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "2", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "1833", 
                        "poNum": "ASDF", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "THEBLOB", 
                        "quantity": "40"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "3", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "229", 
                        "poNum": "FDSA", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "BATMAN", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "4", 
                                "desc": "STUFF"
                            
                        
                    ]
                
            ], 
            "AT5": [], 
            "G62": [
                
                    "date": "20100817", 
                    "datequalifier": "10"
                , 
                
                    "date": "20100817", 
                    "datequalifier": "38"
                
            ], 
            "NTE": [
                
                    "refCode": "OTH", 
                    "desc": "No Touch"
                
            ]
        , 
        
            "Loop310": [
                
                    "N1": 
                        "idCode": "9998000006", 
                        "idQual": "ZZ", 
                        "name": "REDACTED", 
                        "entIdCode": "SF"
                    , 
                    "N3": [
                        
                            "address1": "REDACTED"
                        
                    ], 
                    "G61": [
                        
                            "contactFunctionCode": "CN", 
                            "commNumber": "REDACTED", 
                            "commNumQualifier": "TE", 
                            "name": "REDACTED"
                        
                    ], 
                    "N4": [
                        
                    ]
                
            ], 
            "L11": [], 
            "S5": 
                "stopReasonCode": "LD", 
                "stopSeqNum": "2"
            , 
            "Loop350": [
                
                    "LAD": [], 
                    "OID": 
                        "poNum": "QWERTY", 
                        "refID": "ASDF", 
                        "unitMeasure": "PL", 
                        "quantity": "1"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "1", 
                                "desc": "PORT"
                            
                        
                    ]
                
            ], 
            "AT5": [], 
            "G62": [
                
                    "date": "20100817", 
                    "datequalifier": "10"
                , 
                
                    "date": "20100817", 
                    "datequalifier": "38"
                
            ], 
            "NTE": [
                
                    "refCode": "OTH", 
                    "desc": "Driver Count Required"
                
            ]
        , 
        
            "Loop310": [
                
                    "N1": 
                        "idCode": "9998000070", 
                        "idQual": "ZZ", 
                        "name": "PLACE", 
                        "entIdCode": "ST"
                    , 
                    "N3": [
                        
                            "address1": "PLACE"
                        
                    ], 
                    "G61": [
                        
                            "contactFunctionCode": "CN", 
                            "commNumber": "XXXXXXXXXX", 
                            "commNumQualifier": "TE", 
                            "name": "X"
                        
                    ], 
                    "N4": [
                        
                    ]
                
            ], 
            "L11": [], 
            "S5": 
                "stopReasonCode": "UL", 
                "stopSeqNum": "3"
            , 
            "Loop350": [
                
                    "LAD": [], 
                    "OID": 
                        "poNum": "JOE", 
                        "refID": "SUPERMAN", 
                        "unitMeasure": "PL", 
                        "quantity": "1"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "1", 
                                "desc": "PORT"
                            
                        
                    ]
                
            ], 
            "AT5": [], 
            "G62": [
                
                    "date": "20100817", 
                    "datequalifier": "68"
                , 
                
                    "date": "20100817", 
                    "datequalifier": "54"
                
            ], 
            "NTE": [
                
                    "refCode": "OTH", 
                    "desc": "No Touch"
                
            ]
        , 
        
            "Loop310": [
                
                    "N1": 
                        "idCode": "0000403803", 
                        "idQual": "ZZ", 
                        "name": "REDACTED", 
                        "entIdCode": "ST"
                    , 
                    "N3": [
                        
                            "address1": "REDACTED"
                        
                    ], 
                    "G61": [
                        
                            "contactFunctionCode": "CN", 
                            "commNumber": "0000000000", 
                            "commNumQualifier": "TE", 
                            "name": "REDACTED"
                        
                    ], 
                    "N4": [
                        
                    ]
                
            ], 
            "L11": [
                
                    "qualifier": "DO", 
                    "refID": "THETHING"
                
            ], 
            "S5": 
                "stopReasonCode": "UL", 
                "stopSeqNum": "4"
            , 
            "Loop350": [
                
                    "LAD": [], 
                    "OID": 
                        "weight": "161", 
                        "poNum": "UIP", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "JACK", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "1", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "104", 
                        "poNum": "JKLM", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "SUSAN", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "2", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "1833", 
                        "poNum": "ASDF", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "JOE", 
                        "quantity": "40"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "3", 
                                "desc": "STUFF"
                            
                        
                    ]
                , 
                
                    "LAD": [], 
                    "OID": 
                        "weight": "229", 
                        "poNum": "AAAA", 
                        "weightCode": "L", 
                        "unitMeasure": "CA", 
                        "refID": "ASDF", 
                        "quantity": "6"
                    , 
                    "Loop360": [
                        
                            "Loop365": [], 
                            "L5": 
                                "lineNum": "4", 
                                "desc": "STUFF"
                            
                        
                    ]
                
            ], 
            "AT5": [], 
            "G62": [
                
                    "date": "20100817", 
                    "datequalifier": "68"
                , 
                
                    "date": "20100817", 
                    "datequalifier": "54"
                
            ], 
            "NTE": [
                
                    "refCode": "OTH", 
                    "desc": "Driver Assist Required"
                
            ]
        
    ], 
    "SE": 
        "numSegments": "70", 
        "controlNum": "0002"
    , 
    "Loop100BT": [], 
    "L11": [
        
            "qualifier": "VD", 
            "refID": "SALLY"
        , 
        
            "qualifier": "SI", 
            "refID": "MARK"
        , 
        
            "qualifier": "CR", 
            "refID": "JOE"
        , 
        
            "qualifier": "RB", 
            "refID": "USD"
        , 
        
            "qualifier": "TH", 
            "refID": "REDACTED"
        
    ], 
    "PLD": [], 
    "L3": 
        "weight": "2328", 
        "advances": "0", 
        "rateQual": "FR", 
        "charge": "05", 
        "freightRate": "", 
        "weightQual": "G", 
        "quantity": "59"
    , 
    "B2": 
        "ordernum": "12345", 
        "paymethod": "PP", 
        "scac": "XXXX"
    , 
    "Loop100VI": [
        
            "N1": 
                "name": "REDACTED", 
                "entIdCode": "AA"
            , 
            "G61": [
                
                    "contactFunctionCode": "CN", 
                    "commNumber": "REDACTED", 
                    "contactReference": "0563", 
                    "commNumQualifier": "TE", 
                    "name": "REDACTED"
                , 
                
                    "contactFunctionCode": "IC", 
                    "commNumber": "REDACTED", 
                    "commNumQualifier": "EM", 
                    "name": "REDACTED"
                , 
                
                    "contactFunctionCode": "ZZ", 
                    "name": "REDACTED"
                
            ]
        
    ], 
    "G62": [
        
            "date": "20100827", 
            "timequalifier": "1", 
            "datequalifier": "64", 
            "time": "1302"
        
    ], 
    "Loop100CB": [], 
    "NTE": [
        
            "refCode": "ZZZ", 
            "desc": "26"
        , 
        
            "refCode": "OTH", 
            "desc": "No Touch"
        , 
        
            "refCode": "OTH", 
            "desc": "Driver Count Required"
        , 
        
            "refCode": "OTH", 
            "desc": "No Touch"
        , 
        
            "refCode": "OTH", 
            "desc": "Driver Assist Required"
        
    ], 
    "B2A": 
        "purpose": "00"
    , 
    "N7": [
        
            "equipLength": "4800", 
            "equipHeight": "0", 
            "weight": "2328", 
            "equipWidth": "0", 
            "equipNum": "ZZZZ", 
            "equipType": "TV", 
            "weightQual": "G"
        
    ]

谢谢, T.J.

【问题讨论】:

嘿@tjsimmons,你能告诉我们你的JSON的结构吗? Does anyone know of a good solution to parsing such an object? 显示对象可能会有所帮助。 JSON.parse() 不工作吗? 仅在新浏览器上。如果您希望依赖 JSON,您必须包含 json2.js。 哇伙计..这是一些只有母亲才能爱的 json.... 【参考方案1】:

你的意思是这样的吗?

function iterateAttributesAndFormhtmlLabels(o)
    var s = '';
    for(var a in o)
        if (typeof o[a] == 'object')
            s+='<label><font color=green>'+a+':</font></label><br />';
            s+=iterateAttributesAndFormHTMLLabels(o[a]);
        else
            s+='<label>'+a+': <font color=blue>'+o[a]+'</font></label><br />';
        //end if
    //end for
    return s;
//end function

data = ...;

var html = iterateAttributesAndFormHTMLLabels(data);

不知道它是否适用于所有浏览器,是否适用于 Chrome 和 firefox

干杯, 伊恩

【讨论】:

谢谢,效果很好。我搜索了这个简单的解决方案 2 天:)【参考方案2】:

我很感激您试图让您的问题更具体,但信息不足。

呈现的 json 非常抽象,大多数键都很少或根本没有推断数据含义的上下文,结构非常广泛,使得收集含义的努力成为问题。

“有意义”是一个模糊的、相对的和主观的术语。

请尝试浓缩和澄清您的数据示例,并更具体地说明您将如何提出它,这样您将有更多的运气获得与您的要求相关的答案和指导。

干杯


这是我对原问题的原始回答

在您的页面中包含https://github.com/douglascrockford/JSON-js/blob/master/json2.js。如果浏览器没有原生的JSON,就会填写。

然后

var myobj = JSON.parse(myjsonstring);

自己动手只是一件愚蠢的事情。

祝你好运。

【讨论】:

是的,我的意思是解析为通用的“做一些有意义的事情”。我使用 json2.js 将字符串更改为我上面发布的内容。 @tjs 那么您的下一步将是删除术语“解析”并将其替换为您想要做的有用的事情的描述...... 完成了。当我昨晚发布这个时已经很晚了,我已经盯着它看了一段时间。我在原始帖子中添加了我真正想要对这些信息执行的操作。【参考方案3】:

我建议JQuery's parseJSON() function。

JQuery 的实现将使用浏览器内置的JSON.parse() 函数,如果存在,如果不存在,它将回退到纯javascript 实现。


[edit] 正如@Sky 所指出的,jQuery 实现比json.org 提供的参考实现要简单得多,这可能会在您的JSON 源不一定受信任的情况下出现一些问题。

我的经验是 jQuery 的解析器正确地使用任何有效的 JSON(如果有人能以其他方式显示,我非常希望看到它)。问题是它会消耗许多不是 JSON的东西——也就是说,它会消耗(并评估)任何有效的javascript表达式。由于表达式可能包含函数调用,因此如果您的 JSON 来自不受信任的来源,则会出现安全问题。

但是,如果您的 JSON 的来源是可信的(例如您自己的服务器),那么我认为没有理由产生更严格实施的额外开销(代码大小和性能)。 尤其是如果你因为其他原因已经包含了 jQuery 核心(你可能会也可能不会)。

当然,所有这些都是一个相当迂腐的讨论,因为这两种实现都回退到内置浏览器(如果存在)——在所有现代浏览器中都是如此。我的观点只是 jQuery 实现有其优势,并且在许多情况下是一个完全有效的选择。在其他情况下,json.org 的参考实现可能会更好地为您服务。

【讨论】:

我很难引用一个比 jquery 的功能更弱的 json 实现。 您愿意详细说明吗?许多网站和系统每天都使用 jQuery 的 json 解析器。任何使用 jQuery ajax 函数的人都在隐式使用 jQuery json 实现。 @Sky:我也会感兴趣。 JSON 并不完全是一种复杂的格式,我什至称它为 hard 不正确或不完整地实现它。 @tom et al - jquery 将使用本机 json,如果存在,如果不存在,它会退回到一个非常幼稚的实现,这种实现是不安全的,并且经常在处理完全有效的 json 时出错。仅仅因为许多人毫无疑问地购买了他们出售的东西,即'jquery iz da bomb,duedz',并没有赋予代码功能。我不会在 jquery 或使用它的人身上投下阴影,我经常这样做,但是当我编写应用程序时,我需要我可以依靠的代码,因此我使用它们所基于的代码备份本机实现,json2.js @tom et al - 此外,在当前的本机 json 实现中存在许多记录在案的不一致和错误,为此我修改了 json2.js 的礼貌性质以覆盖本机字符串化和/或解析问题用户代理。【参考方案4】:

您可以使用 JS 模板引擎将您的 JSON 转换为人类可读的 HTML。

这是一个使用 PURE 模板库进行递归的示例:http://beebole.com/pure/documentation/recursion-example/

这里的模板非常通用,使用UL/LI 组合。

或者如果你想在文本框中渲染它,你可以使用JSON.stringify:

document.getElementById('theTextBox').value = JSON.stringify(theJson, null, 2);

上面对stringify 的调用将使JSON 缩进2 个空格。

【讨论】:

以上是关于递归解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章

递归解析 JSON

递归问题;解析 JSON

在 Scala 中使用列表解析递归 JSON 结构

递归解析任意层的json

如何在没有外部递归函数的情况下解析多个嵌套的 JSON 键?

AngularJS将递归JSON解析为对象数组