2012-10-12 113 views
2

我正在使用Newtonsoft JSON.Net來反序列化啓用了PreserveReferencesHandling的對象。 jQuery不支持基於$ ref和$ id語法的引用重新鏈接JSON.Net使用(我不知道jQuery是否支持這個功能)。有JSON.Net的JavaScript序列化程序嗎?

我試着用道格拉斯Crockford的cycle.js但似乎不符合我的對象的工作,返回的對象是相同的這時候傳遞的對象。

我不是難以置信熟悉JSON.Net,但我似乎無法找到任何可以序列化(或解析)其.NET組件輸出的JSON的JavaScript庫。

我該如何完成將對象引用放在一起?

回答

0

你將不得不雙向查閱你的js解析器。技術上保留引用處理是爲了繞過循環引用,也就是說在解析過程中通常會導致堆棧溢出。

JSON沒有處理這個的本地語法。 Newtonsoft版本是一個自定義實現,因此解析JSON將是一個自定義實現。

如果你真的必須保留這樣的引用,XML可能是一個更好的解決方案。這裏有一些json-> xml庫。

下面是分析可能是有用的,或至少是指導一個解決方案: https://blogs.oracle.com/sundararajan/entry/a_convention_for_circular_reference

+1

「Newtonsoft版本是一個自定義實現,因此解析JSON將是一個自定義實現。」是的,我希望別人已經遇到了這個問題,並解決了這個自定義實現。 – Mixcels

+0

用java實現更新。不要認爲編寫一個js解析器來達到相同的結果是很困難的。 – FlavorScape

4

我一直在尋找一個解決這個問題爲好,並結束了黑客道格拉斯Crockford的JSON.retrocycle功能。他的功能不適用於$ ref = 某些數字,但它尋找類似xpath的東西。

這是我的快速和骯髒的版本 - 不要使用這個 - 我沒有做任何清理,它可能應該是一個插件,但它的工作,並且足夠好去得到:

function retrocycle(o) { 
var self = this; 
self.identifiers = []; 
self.refs = []; 

self.rez = function (value) { 

    // The rez function walks recursively through the object looking for $ref 
    // properties. When it finds one that has a value that is a path, then it 
    // replaces the $ref object with a reference to the value that is found by 
    // the path. 

    var i, item, name, path; 

    if (value && typeof value === 'object') { 
     if (Object.prototype.toString.apply(value) === '[object Array]') { 
      for (i = 0; i < value.length; i += 1) { 
       item = value[i]; 
       if (item && typeof item === 'object') { 
        path = item.$ref; 
        if (typeof path === 'string' && path != null) { 
         //self.refs[parseInt(path)] = {}; 

         value[i] = self.identifiers[parseInt(path)] 
        } else { 
         self.identifiers[parseInt(item.$id)] = item; 
         self.rez(item); 
        } 
       } 
      } 
     } else { 
      for (name in value) { 
       if (typeof value[name] === 'object') { 
        item = value[name]; 
        if (item) { 
         path = item.$ref; 
         if (typeof path === 'string' && path != null) { 
          //self.refs[parseInt(path)] = {}; 

          value[name] = self.identifiers[parseInt(path)] 
         } else { 
          self.identifiers[parseInt(item.$id)] = item; 
          self.rez(item); 
         } 
        } 
       } 
      } 
     } 
    } 

}; 
self.rez(o); 
self.identifiers = []; 
} 

使用方法如下:

$.post("url/function", { ID: params.ID }, function (data) { 

     retrocycle(data) 

     // data references should be fixed up now 

    }, "json"); 
0

這是我增強@Dimitri的版本。 @Dimitri代碼有時不能重建引用。如果有人改進了代碼,請告訴我。

Regards, Marco Alves。

if (typeof JSON.retrocycle !== 'function') { 
    JSON.retrocycle = function retrocycle(o) { 
     //debugger; 

     var self = this; 
     self.identifiers = []; 
     self.refs = []; 

     self.buildIdentifiers = function (value) { 
      //debugger; 

      if (!value || typeof value !== 'object') { 
       return; 
      } 

      var item; 

      if (Object.prototype.toString.apply(value) === '[object Array]') { 
       for (var i = 0; i < value.length; i += 1) { 
        item = value[i]; 

        if (!item || !item.$id || isNaN(item.$id)) { 
         if (item) { 
          self.buildIdentifiers(item); 
         } 

         continue; 
        } 

        self.identifiers[parseInt(item.$id)] = item; 
        self.buildIdentifiers(item); 
       } 

       return; 
      } 

      for (var name in value) { 
       if (typeof value[name] !== 'object') { 
        continue; 
       } 

       item = value[name]; 

       if (!item || !item.$id || isNaN(item.$id)) { 
        if (item) { 
         self.buildIdentifiers(item); 
        } 

        continue; 
       } 

       self.identifiers[parseInt(item.$id)] = item; 
       self.buildIdentifiers(item); 
      } 
     }; 

     self.rez = function (value) { 

      // The rez function walks recursively through the object looking for $ref 
      // properties. When it finds one that has a value that is a path, then it 
      // replaces the $ref object with a reference to the value that is found by 
      // the path. 

      var i, item, name, path; 

      if (value && typeof value === 'object') { 
       if (Object.prototype.toString.apply(value) === '[object Array]') { 
        for (i = 0; i < value.length; i += 1) { 
         item = value[i]; 
         if (item && typeof item === 'object') { 

          if (item.$ref) 
           path = item.$ref; 

          if (typeof path === 'string' && path != null) { 
           //self.refs[parseInt(path)] = {}; 

           value[i] = self.identifiers[parseInt(path)]; 
           continue; 
          } 

          //self.identifiers[parseInt(item.$id)] = item; 
          self.rez(item); 
         } 
        } 
       } else { 
        for (name in value) { 
         if (typeof value[name] === 'object') { 
          item = value[name]; 
          if (item) { 
           path = item.$ref; 
           if (typeof path === 'string' && path != null) { 
            //self.refs[parseInt(path)] = {}; 

            value[name] = self.identifiers[parseInt(path)]; 
            continue; 
           } 

           //self.identifiers[parseInt(item.$id)] = item; 
           self.rez(item); 
          } 
         } 
        } 
       } 
      } 

     }; 

     self.buildIdentifiers(o); 
     self.rez(o); 
     self.identifiers = []; // Clears the array 
    }; 
}