`

递归+Delegate模式 解析JSON对象

阅读更多

NOTE: 这里的JSON对象是指已经从JSON格式字符串转为JS对象的对象。所以,我这里要share的不是怎样把一个JSON格式的字符串转换为Javascript JSON对象,而是怎么样把JSON对象里的信息提取成一个一个的类实例。

 

    这里还要提到的是我所采用的提取解析方式主要借鉴于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对象。简单说就是: 一个JSON大对象里每个子对象都用Javascript OO的类实例来表示, 同时这些实例之间的关联关系应该和大JSON对象里表示的一样。

    NOTE: 大JSON对象里的属性名会多一个“@”符号以表示它是属性(这里的这种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方法里的最外层有两个循环,而且这两个循环都是对同一个数据jsonData, 可能你会问为什么呢?如果,我不写这篇blog的话,再过个一年半年的,我只能对你说:"God knows!". 开玩笑的。可能再过一段时间来看代码的话,我还得从头捋,想想都可怕。这就是为什么我要写下这一篇blog.第一个循环是把节点的所以属性存起来,等循环结束后,通过delegate实例把nodeName和它的属性传给delegate实例,然后第二个循环再去遍历节点的子节点(递归方式)。这样做的好处是:在第一个循环结束后,调用了delegate的didParse方法(jsonParser把自己的实例也传过去了),这样在Delegate实例那边就可以有机会改变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);
       }

 这个代码片断里有两处先

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。

 

说到这里,肯定有人会问,为什么不把两个循环合成一个来做呢,这样效率还高一些。不错,那样效率是高,其实之前我就是那样去做的,但是那样没有实现功能。因为

delegate.didParse(self, nodeName, properties);

在最后即在循环外面,大家知道递归的特点就是至底向上,那么不合成一个循环的原因也就有了。因为到递归调用到最底一层时,那时的delegateg还是JSONParser实例化的时候的那个delegte, 所以这样没法把nodeName和properties通过这个delegate实例传给最底一层节点对应的自定义的Javascript类实例。


下面的事就是去慢慢理解了。最重要的事看有没有BUG!!!

 

 

 

 

分享到:
评论

相关推荐

    json字符串递归解析

    JSON格式通常由键值对组成,键用引号括起来,值可以是字符串、数字、布尔值、数组、null或另一个JSON对象。 在处理JSON数据时,我们经常需要对JSON字符串进行解析,将其转化为JavaScript对象以便进一步操作。当JSON...

    Android Studio解析JSON对象

    5. **处理嵌套的JSON对象**:如果JSON对象中还包含了其他JSON对象,可以递归地解析。例如,解析上述示例中的`address`对象: ```java JSONObject addressObject = jsonObject.getJSONObject("address"); String ...

    Java递归算法构造JSON树形结构

    Java 递归算法构造 JSON 树形结构 Java 递归算法构造 JSON 树形结构是指通过 Java 语言使用递归算法将数据库中的菜单表构建成树形的 JSON 格式发送给第三方。这种方法可以将复杂的树形结构数据转换成易于理解和处理...

    使用递归循环读取省市区json文件数据,并保存到数据库中

    本话题涉及的主要知识点包括:JSON解析、递归算法和数据库操作。 1. **JSON解析**: JSON数据通常包含键值对,表示对象或者数组结构。在Python中,可以使用`json`模块来处理JSON数据。例如,`json.load()`函数用于...

    json-c 一个用于c语言的json解析库,很强大

    1. **解析和生成JSON**:`json-c`库提供API,能够将JSON字符串解析成JSON对象,同时也能将JSON对象转换回字符串。这使得开发者可以方便地在C程序中处理JSON数据。 2. **JSON对象模型**:`json-c`使用哈希表来表示...

    Powerbuilder解析json半成品

    2. **创建JSON对象**:在PowerBuilder中,你可以通过Sailfish库创建一个JSON对象,例如`Create jsonObject`,然后使用其提供的方法读取或写入JSON数据。 3. **解析JSON数据**:使用`jsonObject.Parse(jsonString)`...

    PB调用http apiPB解析json

    例如,解析一个表示多级菜单的JSON,可能需要递归地解析每个节点,创建对应的树形结构。 6. **API.pbw文件**:这可能是PowerBuilder的工作区文件,包含了项目中的所有源代码、对象定义和其他设置。打开此文件可以...

    Sql Server解析Json

    这个函数通过遍历 JSON 字符串,寻找开括号和闭括号,然后根据找到的括号来解析对象和数组。具体步骤如下: 1. 寻找第一个开括号的位置 `@FirstObject`。 2. 根据开括号和闭括号的位置,确定当前解析的是对象还是...

    递归循环读取省市区json文件数据,并保存到数据库中(很全面)

    本示例中的“递归循环读取省市区json文件数据,并保存到数据库中”是一个全面的教程,它涵盖了从JSON解析到数据库交互的关键技术。以下是这个过程涉及的主要知识点: 1. **JSON (JavaScript Object Notation)**:...

    递归下降文法-Json字符串转换成Java对象

    用java实现的递归下降文法 将JSon字符串转换成Java对象 为了简单化 忽略了很多情况 仅仅作为初接触编译原理的同学们共勉 User对象有一个Teacher对象 Teacher里有一个Book对象 等等 比如 User user User json User ...

    Python递归解析Json文件

    使用Python递归解析从TCGA下载的metadata.cart.json文件

    asp字符串转json对象类

    2. **解析JSON对象**:逐个解析JSON字符串中的键值对,创建一个内部数据结构来存储这些键值对,如数组或自定义的Object类实例。 3. **创建访问接口**:为这个数据结构提供类似"obj("name")"的访问方法,这可能涉及...

    java FASTJSON 解析复杂JSON实例源码

    例如,如果你有一个包含多个层级的对象,你可以使用`getJSONObject`或`getJSONArray`方法来获取嵌套的JSON对象或数组。之后,你可以递归地解析这些嵌套结构,直到获取到所有的数据。 `JSONTest`示例代码可能包含了...

    二叉树遍历的流程图(递归+非递归+前中后序)

    在本资料中,我们关注的是三种基本的遍历方法:前序遍历、中序遍历和后序遍历,这些方法都可以通过递归和非递归的方式实现。 **前序遍历**: 前序遍历的顺序是根节点 -> 左子树 -> 右子树。递归实现时,首先访问根...

    java解析json格式字符串所需jar包

    5. 对于嵌套的JSON对象,可以递归地调用`getJSONObject("nestedKey")`。 6. 当你需要将Java对象转换为JSON时,可以使用`JSONObject.toJSONObject(yourJavaObject)`。 7. 最后,使用`toString()`方法将JSON对象转换...

    QT5解析json文件demo

    然后,根据数据是JSON对象还是数组,分别调用`parseJsonObject`或`parseJsonArray`进行递归解析。 注意,由于描述中提到"代码支持文件需要稍微修正",这可能意味着实际的代码可能需要针对具体JSON结构进行调整,...

    PB调用http api接口 PB解析json

    例如,如果JSON返回的是一个包含层次结构的菜单,你可以通过递归解析JSON对象,逐级构建数据窗口的行和子数据窗口,以展现菜单结构。同样,如果响应是一个数组,你可以遍历JsonArray,将每个元素插入到数据源中。 ...

    安卓Android源码——解析json_dome.zip

    3. **解析JSON对象**:获取JSON对象中的键值,可以使用`get()`方法。例如,获取上面`jsonObject`的"name"键的值: ```java String name = jsonObject.getString("name"); ``` 4. **解析JSON数组**:对于包含多个...

    VB解析Json转换为Xml

    对于这种情况,你可能需要递归地处理Json对象和数组,将其转化为对应的Xml结构。例如,如果Json对象中有数组,你可以使用循环遍历数组,然后为每个元素创建一个Xml元素。 总的来说,VB.NET提供了足够的工具来处理...

    lua解析json

    在Lua中,我们通常会将JSON对象转换为表格,数组转换为 Lua 数组或表。 在Lua中解析JSON,我们可以编写一个函数,该函数接受一个JSON字符串作为输入,然后使用正则表达式提取其中的关键信息。正则表达式是模式匹配...

Global site tag (gtag.js) - Google Analytics