再帰+Delegateモード解析JSONオブジェクト
53103 ワード
NOTE:ここでJSONオブジェクトとは、JSON形式の文字列からJSオブジェクトに変換されたオブジェクトのことです.だから、私がここでシェアしたいのは、JSON形式の文字列をJavascript JSONオブジェクトに変換する方法ではなく、JSONオブジェクトの情報を1つずつ抽出するクラスインスタンスです.
ここでまた、私が採用した抽出解析方式は主にCocoa touch framworkを考慮している.iPhoneの開発をする前に、Delegate patternについても耳にしたことがありますが、本当に大量に仕事で使ったことはありません.しかし、iPhoneの開発をしたことがある人は、Cocoa touch frameworkの中で重要であると同時に便利で、大量に使われているpatternがDelegateであることを知っているはずで、ほとんどどこにもいません.そこで、iPhoneでの開発経験と自分自身のDelegateとNSXMLParserに対する理解に基づいて、私も同じ方法で複雑なJSONオブジェクトを解析することにしました.
需要:複雑なJSONオブジェクト(データのみfunctionなし)をJSONオブジェクト内部で表される関係によって、同じクラス関係を持つJavascriptクラスのインスタンスに分解します.このJSONオブジェクトはJqueryアクセスRESTfulサービスリターン(サーバ側から返されるJSON文字列はJSOnLibで生成される)であるため、RESTfulサービスから返されるJSON形式文字列はJQueryによってJSONオブジェクトに変換されている.簡単に言えば、1つのJSON大オブジェクトの各サブオブジェクトはJavascript OOのクラスインスタンスで表され、これらのインスタンス間の関連関係は大JSONオブジェクトと同じであるべきである.
NOTE:大JSONオブジェクトの属性名には、属性であることを示す「@」記号が1つ追加されます(ここのJSON形式は服).
オブジェクトのkeyの場合は、「person」などの一般的な文字列で表されます.
解析対象のJSONオブジェクト構造を以下に貼ります.
ハハハハ.見ていてもうんざりしているのではないでしょうか.大丈夫です.ゆっくりしてください.
上のJSONオブジェクトのコードを解析します.
JSONParser.js
Worker.js
Screen.js
コードが貼られています(重要でないものは貼られていないので、解析メカニズム全体に影響しません)、以下に説明しましょう.
上のJSコードの入り口はWorkkerです.jsのparserDataメソッドは,形参jsonDataが先ほど述べたような大きなJSONオブジェクトである.
主にJSOnParserを説明します.jsのrecursiveParseメソッド:
recursiveParseメソッドの最外層には2つのループがあり、この2つのループは同じデータjsonDataに対して行われていますが、なぜですか?もし、私はこのblogを书かないならば、更に1年の半年のを过ぎて、私はあなたに対して言うことしかできません:“God knows!”.冗談だよ.あとしばらくコードを見に来たら、最初から撫でなければならないかもしれませんが、考えてみると怖いです.だから私はこのblogを書きます.1つ目のループはノードの属性を格納し、ループが終了するとdelegateインスタンスを介してnodeNameとその属性をdelegateインスタンスに渡し、2つ目のループはノードのサブノードを巡回する(再帰的に).このような利点は、最初のループが終了するとdelegateのdidParseメソッド(jsonParserが自分のインスタンスも伝えた)が呼び出され、Delegteインスタンス側でjsonParserインスタンスのdelegateを変更する機会が得られる(delegate参照を次のnodeName,propertiesを受信するインスタンスに変更することができ、Screenクラスはこのようにする)ことである.recursiveParseメソッドがサブノードを解析する場合,jsonParserのdelegateは修正後の例である.したがって、そのインスタンスはnodeNameとpropertiesを受信することができます.ただしrecursiveParseメソッドには、次のようなコード・スライスがあります.
このコードの断片には2つの先がある.
また
では、このような目的は何ですか.目的は、子ノードの解析が完了したら、元のdelegateを復元することです.そうでなければ、親ノードと同級のノードが複数ある場合、現在の親ノードおよび以下のノードを解析した後、次の親ノードと同点のノードを解析するときに呼び出します.
の場合、ここのdelegateは前の同級ノードを解析する場合、
メソッドの修正後のdelegateインスタンス.次の親ノードを解析して再度呼び出すと
の場合、本当に期待されるdelegteインスタンスはnodeNameとpropertiesを受信できません.
ここまで言うと、なぜ2つのサイクルを1つにしないのか、効率が高いのかと聞かれるに違いない.いいですね.それは効率が高くて、実は前に私はそうしましたが、それは機能を実現していません.なぜなら
最後にループの外で、再帰の特徴が底から上にあることを知っていれば、ループを合成しない原因もあります.最下層に再帰的に呼び出されると、その時のdelegategはJSOnParserがインスタンス化されたときのdeletteなので、nodeNameとpropertiesをこのdelegateインスタンスを介して最下層ノードに対応するカスタムJavascriptクラスインスタンスに渡すことはできません.
次のことはゆっくり理解することです.最も重要な事はBUGがあるかどうかを见ます!!!
ここでまた、私が採用した抽出解析方式は主にCocoa touch framworkを考慮している.iPhoneの開発をする前に、Delegate patternについても耳にしたことがありますが、本当に大量に仕事で使ったことはありません.しかし、iPhoneの開発をしたことがある人は、Cocoa touch frameworkの中で重要であると同時に便利で、大量に使われているpatternがDelegateであることを知っているはずで、ほとんどどこにもいません.そこで、iPhoneでの開発経験と自分自身のDelegateとNSXMLParserに対する理解に基づいて、私も同じ方法で複雑なJSONオブジェクトを解析することにしました.
需要:複雑なJSONオブジェクト(データのみfunctionなし)をJSONオブジェクト内部で表される関係によって、同じクラス関係を持つJavascriptクラスのインスタンスに分解します.このJSONオブジェクトはJqueryアクセスRESTfulサービスリターン(サーバ側から返されるJSON文字列はJSOnLibで生成される)であるため、RESTfulサービスから返されるJSON形式文字列はJQueryによってJSONオブジェクトに変換されている.簡単に言えば、1つのJSON大オブジェクトの各サブオブジェクトはJavascript OOのクラスインスタンスで表され、これらのインスタンス間の関連関係は大JSONオブジェクトと同じであるべきである.
NOTE:大JSONオブジェクトの属性名には、属性であることを示す「@」記号が1つ追加されます(ここのJSON形式は服).
{
"person":[
{"@name":"handy", "@age":"18"},
{"@name":"wang", "@age":"20"}
]
}
オブジェクトのkeyの場合は、「person」などの一般的な文字列で表されます.
解析対象のJSONオブジェクト構造を以下に貼ります.
{
"screens": {"screen": [
{
"@id": "3",
"@name": "Light",
"@inverseScreenId": "64",
"background": {
"@fillScreen": "true",
"image": {"@src": "lightbackground1274950957643.png"}
},
"absolute": [
{
"@left": "43",
"@top": "108",
"@width": "86",
"@height": "52",
"button": {
"@id": "6",
"@name": "turn on",
"@hasControlCommand": "true"
}
},
{
"@left": "175",
"@top": "108",
"@width": "95",
"@height": "52",
"button": {
"@id": "8",
"@name": "turn off",
"@hasControlCommand": "true"
}
},
{
"@left": "127",
"@top": "174",
"@width": "185",
"@height": "54",
"label": {
"@id": "10",
"@fontSize": "14",
"@color": "#0000FF",
"@text": "light status",
"link": {
"@type": "sensor",
"@ref": "575",
"state": [
{
"@name": "off",
"@value": "light is off"
},
{
"@name": "on",
"@value": "light is on"
}
]
}
}
},
{
"@left": "195",
"@top": "240",
"@width": "50",
"@height": "50",
"switch": {
"@id": "12",
"link": {
"@type": "sensor",
"@ref": "575",
"state": [
{
"@name": "on",
"@value": "power.png"
},
{
"@name": "off",
"@value": "infrared.png"
}
]
}
}
},
{
"@left": "117",
"@top": "16",
"@width": "70",
"@height": "62",
"image": {
"@id": "14",
"@src": "OpenRemote.Logo.30x32.png",
"link": {
"@type": "sensor",
"@ref": "575",
"state": [
{
"@name": "off",
"@value": "lightbulboff1274938256022.png"
},
{
"@name": "on",
"@value": "lightbulb1274938250976.png"
}
]
},
"include": {
"@type": "label",
"@ref": "10"
}
}
},
{
"@left": "142",
"@top": "304",
"@width": "177",
"@height": "54",
"button": {
"@id": "29",
"@name": "To bedroom",
"navigate": {"@toGroup": "27"}
}
},
{
"@left": "142",
"@top": "361",
"@width": "176",
"@height": "52",
"button": {
"@id": "393",
"@name": "To background test",
"navigate": {
"@toGroup": "331",
"@toScreen": "332"
}
}
}
]
},
{
"@id": "64",
"@name": "Light",
"@landscape": "true",
"@inverseScreenId": "3",
"background": {
"@relative": "TOP",
"image": {"@src": "500X3001274943015264.png"}
},
"absolute": [
{
"@left": "184",
"@top": "112",
"@width": "84",
"@height": "82",
"image": {
"@id": "66",
"@src": "OpenRemote.Logo.30x32.png",
"link": {
"@type": "sensor",
"@ref": "575",
"state": [
{
"@name": "off",
"@value": "lightbulboff1274943081675.png"
},
{
"@name": "on",
"@value": "lightbulb1274943077035.png"
}
]
}
}
},
{
"@left": "126",
"@top": "22",
"@width": "212",
"@height": "52",
"label": {
"@id": "68",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "light state",
"link": {
"@type": "sensor",
"@ref": "575",
"state": [
{
"@name": "off",
"@value": "OFF"
},
{
"@name": "on",
"@value": "ON"
}
]
}
}
},
{
"@left": "151",
"@top": "240",
"@width": "150",
"@height": "50",
"label": {
"@id": "322",
"@fontSize": "14",
"@color": "#FFFFFF",
"@text": "Test gesture"
}
}
],
"gesture": [
{
"@id": "105",
"@hasControlCommand": "true",
"@type": "swipe-bottom-to-top"
},
{
"@id": "102",
"@hasControlCommand": "true",
"@type": "swipe-top-to-bottom"
},
{
"@id": "127",
"@hasControlCommand": "true",
"@type": "swipe-left-to-right"
},
{
"@id": "132",
"@hasControlCommand": "true",
"@type": "swipe-right-to-left"
}
]
},
{
"@id": "15",
"@name": "Air_Condition",
"background": {
"@fillScreen": "true",
"image": {"@src": "air1274951021940.png"}
},
"absolute": [
{
"@left": "139",
"@top": "32",
"@width": "110",
"@height": "52",
"label": {
"@id": "18",
"@fontSize": "14",
"@color": "#3366FF",
"@text": "value",
"link": {
"@type": "sensor",
"@ref": "573"
}
}
},
{
"@left": "59",
"@top": "86",
"@width": "198",
"@height": "44",
"slider": {
"@id": "20",
"@vertical": "false",
"@passive": "false",
"link": {
"@type": "sensor",
"@ref": "573"
},
"min": {"@value": "0"},
"max": {"@value": "100"}
}
},
{
"@left": "267",
"@top": "178",
"@width": "44",
"@height": "198",
"slider": {
"@id": "24",
"@thumbImage": "vthumb1274939161708.png",
"@vertical": "true",
"@passive": "false",
"link": {
"@type": "sensor",
"@ref": "573"
},
"min": {
"@value": "0",
"@image": "vmin1274939127956.png",
"@trackImage": "vminTrack1274939151356.png"
},
"max": {
"@value": "100",
"@image": "vmax1274939183784.png",
"@trackImage": "vmaxTrack1274939173529.png"
}
}
},
{
"@left": "59",
"@top": "130",
"@width": "198",
"@height": "44",
"slider": {
"@id": "26",
"@thumbImage": "thumbImage1274939361119.png",
"@vertical": "false",
"@passive": "false",
"link": {
"@type": "sensor",
"@ref": "573"
},
"min": {
"@value": "0",
"@image": "low1274939314970.png",
"@trackImage": "red1274939338142.png"
},
"max": {
"@value": "100",
"@image": "high1274939397163.png",
"@trackImage": "green1274939382473.png"
}
}
},
{
"@left": "39",
"@top": "31",
"@width": "130",
"@height": "52",
"label": {
"@id": "63",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "temperature:"
}
}
]
},
{
"@id": "71",
"@name": "TV",
"background": {
"@fillScreen": "true",
"image": {"@src": "tvbackground1274951037399.png"}
},
"absolute": [
{
"@left": "9",
"@top": "7",
"@width": "284",
"@height": "54",
"label": {
"@id": "98",
"@fontSize": "14",
"@color": "#000000",
"@text": "Test grid layout"
}
},
{
"@left": "14",
"@top": "272",
"@width": "248",
"@height": "52",
"label": {
"@id": "405",
"@fontSize": "14",
"@color": "#000000",
"@text": "Button 'Vol+' is repeatable"
}
}
],
"grid": {
"@left": "52",
"@top": "61",
"@width": "210",
"@height": "200",
"@rows": "4",
"@cols": "3",
"cell": [
{
"@x": "0",
"@y": "0",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "74",
"@name": "On",
"@hasControlCommand": "true"
}
},
{
"@x": "2",
"@y": "0",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "76",
"@name": "Off",
"@hasControlCommand": "true"
}
},
{
"@x": "1",
"@y": "0",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "78",
"@name": "Mute",
"@hasControlCommand": "true"
}
},
{
"@x": "0",
"@y": "2",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "80",
"@name": "Vol-",
"@hasControlCommand": "true"
}
},
{
"@x": "2",
"@y": "2",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "82",
"@name": "Vol+",
"@hasControlCommand": "true",
"@repeat": "true"
}
},
{
"@x": "1",
"@y": "1",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "84",
"@name": "Ch+",
"@hasControlCommand": "true"
}
},
{
"@x": "1",
"@y": "3",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "86",
"@name": "Ch-",
"@hasControlCommand": "true"
}
},
{
"@x": "1",
"@y": "2",
"@rowspan": "1",
"@colspan": "1",
"button": {
"@id": "88",
"@name": "Menu",
"@hasControlCommand": "true"
}
}
]
}
},
{
"@id": "30",
"@name": "Navigate_Buttons",
"background": {
"@fillScreen": "true",
"image": {"@src": "yesanpoh1274939752102.jpg"}
},
"absolute": [
{
"@left": "15",
"@top": "242",
"@width": "26",
"@height": "25",
"image": {
"@id": "33",
"@src": "turtle1274939826027.png"
}
},
{
"@left": "72",
"@top": "22",
"@width": "150",
"@height": "50",
"label": {
"@id": "415",
"@fontSize": "14",
"@color": "#000000",
"@text": "Test gesture"
}
},
{
"@left": "97",
"@top": "76",
"@width": "161",
"@height": "109",
"image": {
"@id": "421",
"@src": "lightbackground1275028518260.jpg"
}
}
],
"grid": {
"@left": "110",
"@top": "262",
"@width": "200",
"@height": "150",
"@rows": "3",
"@cols": "4",
"cell": [
{
"@x": "0",
"@y": "0",
"@rowspan": "1",
"@colspan": "2",
"button": {
"@id": "35",
"@name": "Login",
"navigate": {"@to": "login"}
}
},
{
"@x": "2",
"@y": "0",
"@rowspan": "1",
"@colspan": "2",
"button": {
"@id": "37",
"@name": "Logout",
"navigate": {"@to": "logout"}
}
},
{
"@x": "0",
"@y": "1",
"@rowspan": "1",
"@colspan": "2",
"button": {
"@id": "39",
"@name": "Setting",
"navigate": {"@to": "setting"}
}
},
{
"@x": "2",
"@y": "1",
"@rowspan": "1",
"@colspan": "2",
"button": {
"@id": "44",
"@name": "Back",
"navigate": {"@to": "back"}
}
},
{
"@x": "0",
"@y": "2",
"@rowspan": "1",
"@colspan": "4",
"button": {
"@id": "54",
"@name": "Next screen",
"navigate": {"@to": "nextScreen"}
}
}
]
},
"gesture": [
{
"@id": "416",
"@type": "swipe-bottom-to-top",
"navigate": {"@to": "logout"}
},
{
"@id": "417",
"@type": "swipe-top-to-bottom",
"navigate": {"@to": "login"}
},
{
"@id": "418",
"@type": "swipe-left-to-right",
"navigate": {"@to": "setting"}
}
]
},
{
"@id": "45",
"@name": "Button_Image",
"background": {
"@fillScreen": "true",
"image": {"@src": "whitebackground1274945911286.png"}
},
"absolute": [
{
"@left": "195",
"@top": "310",
"@width": "61",
"@height": "61",
"button": {
"@id": "48",
"@name": "Button",
"default": {"image": {"@src": "default1274940676120.png"}},
"pressed": {"image": {"@src": "pressed1274940704199.png"}}
}
},
{
"@left": "185",
"@top": "23",
"@width": "64",
"@height": "60",
"image": {
"@id": "50",
"@src": "bluerobot1274941389772.png"
}
},
{
"@left": "77",
"@top": "90",
"@width": "168",
"@height": "54",
"button": {
"@id": "52",
"@name": "Previous Screen",
"navigate": {"@to": "previousScreen"}
}
},
{
"@left": "76",
"@top": "163",
"@width": "179",
"@height": "56",
"button": {
"@id": "56",
"@name": "To livingroom",
"navigate": {"@toGroup": "2"}
}
},
{
"@left": "81",
"@top": "245",
"@width": "168",
"@height": "54",
"button": {
"@id": "58",
"@name": "Air condition",
"navigate": {
"@toGroup": "2",
"@toScreen": "15"
}
}
},
{
"@left": "31",
"@top": "314",
"@width": "150",
"@height": "50",
"label": {
"@id": "318",
"@fontSize": "14",
"@color": "#000000",
"@text": "Pressed button:"
}
},
{
"@left": "23",
"@top": "22",
"@width": "150",
"@height": "50",
"label": {
"@id": "320",
"@fontSize": "14",
"@color": "#000000",
"@text": "Image:"
}
}
]
},
{
"@id": "332",
"@name": "Absolute_10",
"background": {
"@absolute": "10,10",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": [
{
"@left": "127",
"@top": "92",
"@width": "161",
"@height": "52",
"label": {
"@id": "371",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Absolut (10,10)"
}
},
{
"@left": "93",
"@top": "350",
"@width": "150",
"@height": "52",
"button": {
"@id": "391",
"@name": "To livingroom",
"navigate": {
"@toGroup": "2",
"@toScreen": "3"
}
}
}
]
},
{
"@id": "335",
"@name": "Left",
"background": {
"@relative": "LEFT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "128",
"@top": "73",
"@width": "150",
"@height": "50",
"label": {
"@id": "373",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Left"
}
}
},
{
"@id": "339",
"@name": "Top",
"background": {
"@relative": "TOP",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "84",
"@top": "82",
"@width": "150",
"@height": "50",
"label": {
"@id": "375",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Top"
}
}
},
{
"@id": "343",
"@name": "Right",
"background": {
"@relative": "RIGHT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "46",
"@top": "73",
"@width": "150",
"@height": "50",
"label": {
"@id": "377",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Right"
}
}
},
{
"@id": "347",
"@name": "Bottom",
"background": {
"@relative": "BOTTOM",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "83",
"@top": "63",
"@width": "150",
"@height": "50",
"label": {
"@id": "379",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Bottom"
}
}
},
{
"@id": "351",
"@name": "Top_Left",
"background": {
"@relative": "TOP_LEFT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "122",
"@top": "80",
"@width": "150",
"@height": "50",
"label": {
"@id": "381",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Top_Left"
}
}
},
{
"@id": "355",
"@name": "Top_Right",
"background": {
"@relative": "TOP_RIGHT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "45",
"@top": "83",
"@width": "150",
"@height": "50",
"label": {
"@id": "383",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Top_Right"
}
}
},
{
"@id": "359",
"@name": "Center",
"background": {
"@relative": "CENTER",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "78",
"@top": "72",
"@width": "150",
"@height": "50",
"label": {
"@id": "385",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Center"
}
}
},
{
"@id": "363",
"@name": "Bottom_Left",
"background": {
"@relative": "BOTTOM_LEFT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "128",
"@top": "65",
"@width": "150",
"@height": "50",
"label": {
"@id": "387",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Bottom_Left"
}
}
},
{
"@id": "367",
"@name": "Bottom_Right",
"background": {
"@relative": "BOTTOM_RIGHT",
"image": {"@src": "yesanpo1275017627763.jpg"}
},
"absolute": {
"@left": "41",
"@top": "64",
"@width": "150",
"@height": "50",
"label": {
"@id": "389",
"@fontSize": "14",
"@color": "#FF6600",
"@text": "Bottom_Right"
}
}
}
]},
"groups": {"group": [
{
"@id": "2",
"@name": "Livingroom",
"include": [
{
"@type": "screen",
"@ref": "3"
},
{
"@type": "screen",
"@ref": "64"
},
{
"@type": "screen",
"@ref": "15"
},
{
"@type": "screen",
"@ref": "71"
}
]
},
{
"@id": "27",
"@name": "Bedroom",
"include": [
{
"@type": "screen",
"@ref": "30"
},
{
"@type": "screen",
"@ref": "45"
}
]
},
{
"@id": "331",
"@name": "BackgroundTest",
"include": [
{
"@type": "screen",
"@ref": "332"
},
{
"@type": "screen",
"@ref": "335"
},
{
"@type": "screen",
"@ref": "339"
},
{
"@type": "screen",
"@ref": "343"
},
{
"@type": "screen",
"@ref": "347"
},
{
"@type": "screen",
"@ref": "351"
},
{
"@type": "screen",
"@ref": "355"
},
{
"@type": "screen",
"@ref": "359"
},
{
"@type": "screen",
"@ref": "363"
},
{
"@type": "screen",
"@ref": "367"
}
]
}
]}
}
ハハハハ.見ていてもうんざりしているのではないでしょうか.大丈夫です.ゆっくりしてください.
上のJSONオブジェクトのコードを解析します.
JSONParser.js
JSONParser = (function() {
return function(jsonDataParam, delegateParam) {
var self = this;
var jsonData = jsonDataParam;
var delegate = delegateParam;
this.startParse = function() {
recursiveParse(null, jsonData);
};
this.setDelegate = function(delegateParam) {
delegate = delegateParam;
};
function recursiveParse(nodeName, jsonData) {
var properties = {};
var isLeaf = true;
for (var key in jsonData) {
var value = jsonData[key];
if (key.toString().indexOf("@") === 0) {
properties[key] = value;
} else {
isLeaf = false;
}
}
if (nodeName != null) {
delegate.didParse(self, nodeName, properties);
}
if (isLeaf) {
return;
}
for (var key in jsonData) {
var value = jsonData[key];
if (key.toString().indexOf("@") === 0) {
continue;
}else if (Object.prototype.toString.apply(value) === "[object Array]") {
for(var index in value) {
var oldDelegate = delegate;
recursiveParse(key, value[index]);
self.setDelegate(oldDelegate);
}
} else {
var oldDelegate = delegate;
recursiveParse(key, value);
self.setDelegate(oldDelegate);
}
}
}
};
})();
Worker.js
Worker = (function() {
return function() {
this.parseJSONData(jsonData) {
var jsonParser = new JSONParser(jsonData, self);
jsonParser.startParse();
}
// Delegate methods of JSONParser
this.didParse = function(jsonParser, nodeName, properties) {
if (nodeName == "screen") {
RenderDataDB.getInstance().addScreen(new Screen(jsonParser, properties));
} else if (nodeName == "group") {
RenderDataDB.getInstance().addGroup(new Group(jsonParser, properties));
}
};
}
})();
Screen.js
Screen = (function() {
return function(jsonParser, properties) {
// For extend
Screen.superClass.constructor.call(this, jsonParser, properties);
var self = this;
this.background = null;
// Delegate method of JSONParser.
this.didParse = function(jsonParser, nodeName, properties) {
if (nodeName == "background") {
this.background = new Background(jsonParser, properties);
} else if (nodeName == "absolute") {
// TODO
}
};
// Private methods
function init(jsonParser, properties) {
jsonParser.setDelegate(self);
self.className = "Screen";
}
// Init jobs
init(jsonParser, properties);
}
})();
ClassUtils.extend(Screen, BaseModel);
コードが貼られています(重要でないものは貼られていないので、解析メカニズム全体に影響しません)、以下に説明しましょう.
上のJSコードの入り口はWorkkerです.jsのparserDataメソッドは,形参jsonDataが先ほど述べたような大きなJSONオブジェクトである.
主にJSOnParserを説明します.jsのrecursiveParseメソッド:
recursiveParseメソッドの最外層には2つのループがあり、この2つのループは同じデータjsonDataに対して行われていますが、なぜですか?もし、私はこのblogを书かないならば、更に1年の半年のを过ぎて、私はあなたに対して言うことしかできません:“God knows!”.冗談だよ.あとしばらくコードを見に来たら、最初から撫でなければならないかもしれませんが、考えてみると怖いです.だから私はこのblogを書きます.1つ目のループはノードの属性を格納し、ループが終了するとdelegateインスタンスを介してnodeNameとその属性をdelegateインスタンスに渡し、2つ目のループはノードのサブノードを巡回する(再帰的に).このような利点は、最初のループが終了するとdelegateのdidParseメソッド(jsonParserが自分のインスタンスも伝えた)が呼び出され、Delegteインスタンス側でjsonParserインスタンスのdelegateを変更する機会が得られる(delegate参照を次のnodeName,propertiesを受信するインスタンスに変更することができ、Screenクラスはこのようにする)ことである.recursiveParseメソッドがサブノードを解析する場合,jsonParserのdelegateは修正後の例である.したがって、そのインスタンスはnodeNameとpropertiesを受信することができます.ただしrecursiveParseメソッドには、次のようなコード・スライスがあります.
else if (Object.prototype.toString.apply(value) === "[object Array]") {
for(var index in value) {
var oldDelegate = delegate;
recursiveParse(key, value[index]);
self.setDelegate(oldDelegate);
}
} else {
var oldDelegate = delegate;
recursiveParse(key, value);
self.setDelegate(oldDelegate);
}
このコードの断片には2つの先がある.
var oldDelegate = delegate;
また
self.setDelegate(oldDelegate);
では、このような目的は何ですか.目的は、子ノードの解析が完了したら、元のdelegateを復元することです.そうでなければ、親ノードと同級のノードが複数ある場合、現在の親ノードおよび以下のノードを解析した後、次の親ノードと同点のノードを解析するときに呼び出します.
delegate.didParse(self, nodeName, properties);
の場合、ここのdelegateは前の同級ノードを解析する場合、
delegate.didParse(self, nodeName, properties);
メソッドの修正後のdelegateインスタンス.次の親ノードを解析して再度呼び出すと
delegate.didParse(self, nodeName, properties);
の場合、本当に期待されるdelegteインスタンスはnodeNameとpropertiesを受信できません.
ここまで言うと、なぜ2つのサイクルを1つにしないのか、効率が高いのかと聞かれるに違いない.いいですね.それは効率が高くて、実は前に私はそうしましたが、それは機能を実現していません.なぜなら
delegate.didParse(self, nodeName, properties);
最後にループの外で、再帰の特徴が底から上にあることを知っていれば、ループを合成しない原因もあります.最下層に再帰的に呼び出されると、その時のdelegategはJSOnParserがインスタンス化されたときのdeletteなので、nodeNameとpropertiesをこのdelegateインスタンスを介して最下層ノードに対応するカスタムJavascriptクラスインスタンスに渡すことはできません.
次のことはゆっくり理解することです.最も重要な事はBUGがあるかどうかを见ます!!!