2012-11-07 3 views
7

これは一般的な問題ではあるが解決策を見つけることができないと考えている。 JSON設定ファイルを使用して、オブジェクトと配列を含むjQueryオブジェクトを拡張します。jQueryを修正すると、オブジェクト内の配列アイテムがプッシュされますが、他のオブジェクトが拡張されます

オブジェクトと単純なプロパティについては、(extendがうまくいけば)上書きしたいです。

アレイの場合、既存のアイテムが存在する場合と存在しない場合があります。

現在のアレイは、単に最初の要素

var sourceObj = {propterty:"change Me",anArray:[{name:"first"},{name:"second"}]}, 
    configJSON = '{"propterty":"New Val","anArray":[{"name":"third"}]}', 
    configObj = JSON.parse(configJSON); 

$.extend(true,sourceObj,configObj); 

http://jsfiddle.net/PmuwV/

を上書きこれが返されます。

{propterty:"New Val" , anArray:[{name:"third"},{name:"second"}} 

私が代わりに取得することができます。

{propterty:"New Val",anArray:[{name:"first"},{name:"second"},{name:"third"}]} 

ALSOは "最初の"オブジェクトと "2番目の"オブジェクトを更新できますか?

"anArray":[{"name":"second","newProp":"add newProp to second"}] 

は/ extend配列アイテムを比較して拡張したり、そのような「名前」などのいくつかのルールに基づいて、または設定されたプロパティ値を追加するように修正されなければならないだろうか?

アドバイスや参考に感謝します。重複がクリーンアップする必要がありますするアレイ上の私はjqueryのマージに追加

+0

これは私がそれを行う可能性があることがわかりました最も近いように思わ - http://stackoverflow.com/questions/3748697/jquery-extend-arra y-of-objects –

+0

'$ .extend'の通常の使用は、ユーザ指定のオプションをデフォルトとマージするためのものです。この場合、通常、元のオブジェクト内のプロパティを新しいプロパティで完全に置き換えるのが最善です。配列プロパティを追加することは、一般に使用されている方法には合いません。これは何のために必要なのですか? – Barmar

+0

@Barmar jQueryオブジェクト自体に新しい関数/メソッドを拡張することを含む、他の多くのものがあります。 – charlietfl

答えて

2

私はこのソリューションを使用How can I merge properties of two JavaScript objects dynamically?から修正http://jsfiddle.net/PmuwV/2/JavaScript equivalent of jQuery's extend method

から(isDOMNodeが必要です) (はい、私はあまりにも汚い感じ)差し替え後 extendのJqueryソースは非常によく似ていますが、私はこれをより読みやすくすることができました。

function mergeRecursive() { 
    // _mergeRecursive does the actual job with two arguments. 
    var _mergeRecursive = function (dst, src) { 
    if (isDOMNode(src) || typeof src!=='object' || src===null) { 
     return dst; 
    } 

    for (var p in src) { 

//my added bit here - [SB] 
     if ($.isArray(src[p])){ 
      $.merge(dst[p],src[p]); 
      var dupes = {}, 
       singles = []; 
      $.each( dst[p], function(i, el) { 
      if ((dupes[el.name] > -1) && (el.name)) { 
       $.extend(singles[dupes[el.name]],el); 
      }else{ 
        if (el.name){ 
        dupes[el.name] = i; 
        } 
       singles.push(el); 
      } 
     }); 
     dst[p] = singles; 
     } 
     continue;   
     } 
//the rest is original - [SB] 

     if(!src.hasOwnProperty(p)) continue; 
     if (src[p]===undefined) continue; 
     if (typeof src[p]!=='object' || src[p]===null) { 
     dst[p] = src[p]; 
     } else if (typeof dst[p]!=='object' || dst[p]===null) { 
     dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]); 
     } else {    
     _mergeRecursive(dst[p], src[p]); 
     } 
    } 
    return dst; 
    } 

    // Loop through arguments and merge them into the first argument. 
    var out = arguments[0]; 
    if (typeof out!=='object' || out===null) return out; 
    for (var i=1, il=arguments.length; i<il; i++) { 
    _mergeRecursive(out, arguments[i]); 
    } 
    return out; 
} 
+0

http://jsfiddle.net/PmuwV/5/で更新され、特定の一致するプロパティを持つ重複する配列オブジェクトをマージする –

+0

同様のものが必要なので、私はあなたのアンダースコアを少し変更しました:http://codepen.io/clouddueling/pen/nFDCH –

+1

良い解決策ですが、上記のコードで2つのバグが見つかりました。そのため、更新されたコードで「回答」を追加しました。 – user3708842

2

それはlodash library

var targetObj = { 
    customerId: "123", 
    orders: [ 
     "item1", "item2" 
    ] 
}; 

var otherObj = { 
    customerName: "John", 
    orders: [ 
     "item3", "item4" 
    ] 
}; 

_.merge(targetObj, otherObj, function (a, b) { 
    if (_.isArray(a)) { 
    return a.concat(b); 
    } 
}); 

結果があると非常に簡単です:

targetObj = { 
    customerId: "123", 
    customerName: "John", 
    orders: [ 
     "item1", "item2", "item3", "item4" 
    ]  
} 
+0

ありがとう!これは完全に機能しました! – swrobel

+1

2016年以降にこれを読んだ人には、今日の例の正しいlodash関数は '_.mergeWith()'だと思われます。 – AsGoodAsItGets

0

私はこれが古いですけど、私はこの記事を見つけ、上記のスティーブ黒人のコードを使用しますが、いくつかのを見つけましたバグ:

  1. isArrayセクションの 'continue'の前に余分な '}'があります。
  2. ソースはまったくの配列を持っていなかった場合、それは エラーをスローしていましたので、私はそう完成したコードは次のようになります

    if (!dst[p]) { 
        dst[p] = src[p]; 
        continue; 
    } 
    

でIsArrayセクションにこれを追加しました:

function isDOMNode(v) { 
    if (v===null) return false; 
    if (typeof v!=='object') return false; 
    if (!('nodeName' in v)) return false; 
    var nn = v.nodeName; 
    try { 
     v.nodeName = 'is readonly?'; 
    } catch (e) { 
     return true; 
    } 
    if (v.nodeName===nn) return true; 
    v.nodeName = nn; 
    return false; 
} 

function mergeRecursive() { 
    // _mergeRecursive does the actual job with two arguments. 
    var _mergeRecursive = function (dst, src) { 
     if (isDOMNode(src) || typeof src!=='object' || src===null) { 
      return dst; 
     } 

     for (var p in src) { 
      if ($.isArray(src[p])) { 
       if (!dst[p]) { 
        dst[p] = src[p]; 
        continue; 
       } 
       $.merge(dst[p],src[p]); 
       var dupes = {}, singles = []; 
       $.each(dst[p], function(i, el) { 
        if ((dupes[el.name] > -1) && (el.name)) { 
         $.extend(singles[dupes[el.name]],el); 
        } else { 
         if (el.name) { 
          dupes[el.name] = i; 
         } 
        singles.push(el); 
        } 
       }); 
       dst[p] = singles; 
       continue;   
      } 

      if (!src.hasOwnProperty(p)) continue; 
      if (src[p]===undefined)  continue; 
      if (typeof src[p]!=='object' || src[p]===null) { 
       dst[p] = src[p]; 
      } else if (typeof dst[p]!=='object' || dst[p]===null) { 
       dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]); 
      } else {    
       _mergeRecursive(dst[p], src[p]); 
      } 
     } 
     return dst; 
    } 

    // Loop through arguments and merge them into the first argument. 
    var out = arguments[0]; 
    if (typeof out!=='object' || out===null) return out; 
    for (var i=1, il=arguments.length; i<il; i++) { 
     _mergeRecursive(out, arguments[i]); 
    } 
    return out; 
} 
0
<html> 
<head> 
<script type="text/javascript" src="./jquery-2.1.3.js"></script> <!-- for json extend/merge --> 
<script type="text/javascript" src="./jQuery.extendext.min.js"></script> <!-- for json extend/merge - with array extend (instead of array overwrite) - https://github.com/mistic100/jQuery.extendext --> 

<script> 
var jsonResult = {}; 
var json1 = 
{ 
    "properties": 
    { 
     "street_address": { "type": "string" }, 
     "city": { "type": "string" }, 
     "state": { "type": "string" } 
    }, 
    "required": ["street_address", "city", "state"] 
}; 
var json2 = 
{ 
    "properties": 
    { 
     "country": { "type": "string" }, 
     "country-dial-code": { "type": "integer" }, 
     "country-short": { "type": "string" } 
    }, 
    "required": ["country", "country-dial-code", "country-short"] 
}; 
$.extendext(true, 'extend', jsonResult, json1, json2); 
console.log(JSON.stringify(jsonResult)); 
/* output -> 
{ "properties": 
    { "street_address":{"type":"string"}, 
     "city":{"type":"string"}, 
     "state":{"type":"string"}, 
     "country":{"type":"string"}, 
     "country-dial-code":{"type":"integer"}, 
     "country-short":{"type":"string"} 
    }, 
    "required":["street_address","city","state","country","country-dial-code","country-short"] 
} 
*/ 
</script> 
</head> 
<body> 
</body> 
</html> 
+0

https://github.com/mistic100/jQuery.extendext –

+0

キー "F12"をビューコンソール –

関連する問題