递归解析 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的主要内容,如果未能解决你的问题,请参考以下文章