Re: [討論] JSON Parse

作者: CindyLinz (Cindy Wang)   2014-10-08 16:42:48
※ 引述《b60413 (None)》之銘言:
: 我有一筆很大的json資料(萬筆以上)需要parse,
: 可是實際上每次在存取時,
: 都只是需要其中的10幾筆資料,
: 一次將資料轉換成JSON物件又會吃掉很多記憶體,
: 所以想要用正規式做字串分析,
: 但寫出來的正規式實在又臭又長,
: 因此想跟板友討教是否有更簡便的寫法,
: 最大的問題在於每筆資料的第18欄可能是陣列,
: 導致無法使用\[.*?\]來切割,
: 資料內容大約如下:
: {
: "0000001":[1,2,0,0,0,0,0,0,0,0,0,0,1,1,"0.0","0.0",3,0,0,0,0,0,7],
: "0000002":[2,2,0,0,0,0,0,0,0,0,0,0,1,1,"0.0","0.0",3,0,1,0,0,0,7],
: "0000003":[3,2,0,0,0,0,0,0,0,0,0,0,1,1,"0.0","0.0",3,0,[1,1,1],0,0,0,7]
: }
: 目前使用的正規式如下:
: \"(0000002|0000003)\":\[((.+?),+){18}(?(?=\d+).+?|\[.+?\]).*?\]
「正規的」正規表示式應該沒辦法處理 JSON 這種有遞迴結構的東西..
不過如果是 perl 這種有擴充的正規表示式倒是可以, 我試寫了兩個版本,
第一個是比較短, 但很難讀的版本:
if( $line =~ /
"(0000002|0000003)":\[
((
\[(|(?-2)(,(?-3))*)\]|
\{(|(?-4):(?-4)(,(?-5):(?-5))*)\}|
"(\\.|[^"])*"|
'(\\.|[^'])*'|
[^,]+
),){18}
((?-8))
(,(?-9))*
\]/x ) {
print "Y $10\n";
} else {
print "N\n";
}
第二個是比較長, 但比較好讀的版本:
if( $line =~ /
(?(DEFINE)
(?<ITEM> \s*( (?&ARRAY) | (?&OBJECT) | (?&STRING) | (?&OTHER) )\s* )
(?<ARRAY> \[( | (?&ITEM) (, (?&ITEM))* )\] )
(?<OBJECT> \{( | (?&ITEM) : (?&ITEM) (, (?&ITEM) : (?&ITEM) )* )\} )
(?<STRING> " (\\.|[^"])* " | ' (\\.|[^'])* ' )
(?<OTHER> [^,]* )
)
"(0000002|0000003)": \[ ((?&ITEM),){18} (?<CATCH> (?&ITEM)) (,(?&ITEM))* \]
/x ) {
print "Y $+{CATCH}\n";
} else {
print "N\n";
}
發現原 po 需要的好像不用完整的 JSON.. XD
不過都寫那麼多了留著好惹.. XD

Links booklink

Contact Us: admin [ a t ] ucptt.com