2012-01-09 5 views
16

AJAXを使用する場合、私のサーバーからJSONオブジェクト(別名Javascript)の形でJavascriptにオブジェクトを渡す傾向があります。私のJavascript内の特定の関数は、私が使用しているオブジェクトの特定の型に依存しています。たとえば、電話番号を使用することができます。私はコンストラクタを持っています:JavascriptオブジェクトへのJSONオブジェクトのマッピング

function PhoneNumber(number, type, isPrimary, contactId, id, className) { 
    this.number = number; 
    this.type = type; 
    this.isPrimary = isPrimary; 
    this.contactId = contactId; 
    this.id = id; 
    this.className = className; 
} 

私はJavascriptで電話番号オブジェクトを作成するときに使用します。私はJSでオブジェクトを作成しない場合もありますが、サーバーからオブジェクトを取得するので、まったく同じフィールドを持つ汎用オブジェクトの形になります。私のコードはこのような何かを使用して、特定の種類に依存しているときにこのような状況で

var objType = objArray[i].constructor.name; 
var mappedObj; 

switch(objType) { 
    case 'PhoneNumber': 
     currentArray = currentArray.phone; 
     //Convert response to javascript object. 
     mappedObj = mapPhone(jsonResponse[i]); 
     break; 
    case 'Email': 
     currentArray = currentArray.email; 
     mappedObj = mapEmail(jsonResponse[i]); 
     break; 
    case 'Address': 
     currentArray = currentArray.address; 
     mappedObj = mapAddress(jsonResponse[i]); 
     break; 
    case 'Website': 
     currentArray = currentArray.website; 
     mappedObj = mapWebsite(jsonResponse[i]); 
} 

、私は、オブジェクトのコンストラクタの名前を確認し、その名前に基づいて特定の変数を設定します。私が名前をチェックするオブジェクトがサーバーからのJSONである場合、それは単に私にジェネリックな "Object"レスポンスを与え、コードは機能しません。

function mapPhone(phoneObj) { 
    var id = phoneObj.id; 
    var contactId = phoneObj.contactId; 
    var number = phoneObj.number; 
    var type = phoneObj.type; 
    var primary = phoneObj.isPrimary; 
    var className = phoneObj.className; 
    var phoneNumber = new PhoneNumber(number, type, primary, contactId, id, className); 
    return phoneNumber; 
} 

これはうまくいきますが、少し冗長であるようです。これはJSONオブジェクトの問題を解決する最善の方法ですか、それともより良い解決策ですか?私はこれが "これを可能な限り最善の方法でやっているのですか?"と思っていますが、このタイプのロジックをJavascriptコードで繰り返し、私は別の意見を得るかもしれません。これを行うための適切な方法は、私は時間をかけてそれを修正しなければなりません。

EDIT:プロジェクトでjQueryを使用するため、jQueryソリューションを受け入れることになりました。しかし、jQueryオプションを見つける前に、私のために働いていた複数のソリューションもあります。彼らはきれいで効率的ではありませんでした。

+4

* "JSONオブジェクト(別名Javascriptを)" * JSONはJavaScriptを別名ではありません。それは独自の構文と仕様を持っているため、独自の名前を持っています。 –

答えて

25

以下の例では、オブジェクトとJSONオブジェクトで同じプロパティを使用する必要があります。

これは、基本的に新しいPhoneNumberオブジェクトを作成し、JSONオブジェクトのすべてのプロパティをそのオブジェクトにコピーします。 $.extend()メソッドはjQueryのメソッドですが、同様のメソッドとしても使用できます。 Underscore.jsまたは他のjsライブラリ/フレームワークの1つ。

+0

私はjQueryを使用していますので、これは__proto__を使ってプロトタイプにアクセスする必要はありません。私にとってはさらに簡単な解決策です。 – ryandlf

+3

あなたが角度を使うならば、あなたは 'var phoneNumber = angular.copy(あなたのJSONObject、新しいPhoneNumber())'を行うことができます。私はその構文の権利を持っていないかもしれませんが、あなたはそれを行うことができ、それはあなたが望む機能です! – Chris

+1

角度については、angular.copy()、angular.extend()またはangular.merge()のいずれかを使用できます。 Copyは新しいオブジェクトのプロパティを取り除き、ソースオブジェクトのプロパティをクローンします。 ExtendとMergeは、新しいオブジェクトの既存のプロパティを維持しながら、ソースオブジェクトのプロパティを新しいオブジェクトにもたらします(それぞれ浅いコピーと深いコピーを介して)。 http://davidcai.github.io/blog/posts/copy-vs-extend-vs-merge/ – Nhan

1

旧式のブラウザをサポートしていない場合は、Object.createを使用してのマッピングを実行できます。

DEMO

function makeThisExtend(obj, CtorFunc) { 
    for (var k in obj) 
     if ({}.hasOwnProperty.call(obj, k)) 
      obj[k] = { value: obj[k] }; 

    return Object.create(CtorFunc.prototype, obj); 
} 

var objFromServer = { Number: "123", id: 5 }; 
objFromServer = makeThisExtend(objFromServer, PhoneNumber); 


alert(objFromServer.Number + " " + objFromServer.id); //123 5 
alert(objFromServer.constructor); //function PhoneNumber ... 
2

を私の知る限り、あるすべてのものに(つまり、シム2番目のパラメータを受け付けませんので、。MDN-中でシム少なくともシムはは、古いブラウザは修正されませんドロップ)

// define a class 
var Foo = function(name) { 
    this.name = name; 
} 
// make a method 
Foo.prototype.shout = function() { 
    return "I am " + this.name; 
} 
// make a simple object from JSON: 
var x = JSON.parse('{ "name": "Jason" }'); 
// force its class to be Foo 
x.__proto__ = Foo.prototype; 
// the method works 
x.shout(); 

残念ながら、IEは__proto__アクセサをサポートしていないので、何をする必要があるだろうことはまずオブジェクトの空のインスタンスを作成している、そしてちょうど警官:IE、あなたはこれを行うことができませんYのすべてが上:

// make a simple object from JSON: 
var x = JSON.parse('{ "name": "Jason" }'); 
// make an empty Foo 
var y = Object.create(Foo.prototype); 
// copy stuff over 
for (a in x) { 
    y[a] = x[a]; 
} 
y.shout(); 

これらのアプローチの両方がDRYそれを維持、かなり多くの一般的なごmapWhatever機能よりも。

+0

クリーナーソリューションのように見えます。これは私が探していたものです、ありがとうございます。私のテストがうまくいくとすれば、これは受け入れられた答えのようです。 – ryandlf

+1

アマダンが答えを発表した2年後に下落した。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto –

3

これと同様の質問は面白い答えをたくさん持っている:

Parse JSON String into a Particular Object Prototype in JavaScript

は、ポスターの自身の答えをオフに基づいて、私はこれがあなたのための効果的な解決策になると思う:

function recastJSON(jsonObject) { 
    // return generic object if objectType is not specified 
    if (!jsonObject.objectType) 
     return jsonObject; 

    // otherwise create a new object of type specified 
    var obj = eval('new '+jsonObject.objectType+'()'); 
    for(var i in jsonObject) 
     obj[i] = jsonObject[i]; 
    return obj; 
} 

あなたはしますインスタンス化するjavascriptクラスを定義するために受け取っているJSONオブジェクトにobjectTypeを追加する必要があります。次に、この関数を呼び出すと、そのオブジェクトをその型にキャストし、データをコピーします(変数 'objectType'を含む)。お使いの電話番号の例を使用

、あなたのコードは次のようになります。

// generic object from JSON 
var genericObject = {objectType:'PhoneNumber', number:'555-555-5555', type:'home', primary:true, contactId:123, id:1234, className:'stdPhone'}; 
var phoneObject = recastJSON(genericObject); 
関連する問題