जेलों को JQuery से सही ढंग से डिकोड नहीं करना (सरणी पूर्णांक कुंजियों के साथ हैश बनना)


89

हर बार जब मैं jQuery ऑब्जेक्ट्स की एक सरणी को jQuery के साथ पटरियों पर पोस्ट करना चाहता हूं, तो मुझे यह समस्या है। अगर मैं ऐरे को बढ़ाता हूं तो मैं देख सकता हूं कि jQuery अपना काम सही ढंग से कर रहा है:

"shared_items"=>"[{\"entity_id\":\"253\",\"position\":1},{\"entity_id\":\"823\",\"position\":2}]"

लेकिन अगर मैं अभी इसे AJAX कॉल के डेटा के रूप में देता हूं तो मुझे यह मिलेगा:

"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}

अगर मैं सिर्फ एक सादा सरणी भेजता हूँ तो यह काम करता है:

"shared_items"=>["entity_253"]

क्यों रेल उस अजीब हैश के लिए सरणी बदल रहा है? दिमाग में आने का एकमात्र कारण यह है कि रेल सामग्री को सही ढंग से नहीं समझ सकता है क्योंकि यहां कोई प्रकार नहीं है (क्या इसे jQuery कॉल में सेट करने का कोई तरीका है?)

Processing by SharedListsController#create as 

धन्यवाद!

अद्यतन: मैं डेटा को एक सरणी के रूप में भेज रहा हूं, न कि एक स्ट्रिंग और .push()फ़ंक्शन के उपयोग से गतिशील रूप से सरणी बनाई गई है। के साथ $.postऔर $.ajax, एक ही परिणाम की कोशिश की ।

जवाबों:


169

यदि कोई व्यक्ति इस पर ठोकर खाता है और एक बेहतर समाधान चाहता है, तो आप .axax कॉल में "contentType: 'application / json'" विकल्प को निर्दिष्ट कर सकते हैं और रेल्स को JSON ऑब्जेक्ट को ठीक से पार्स-कीड वाले हैश में गार्बिंग किए बिना ठीक से पार्स कर सकते हैं- स्ट्रिंग मान।

इसलिए, संक्षेप में, मेरी समस्या यह थी कि:

$.ajax({
  type : "POST",
  url :  'http://localhost:3001/plugin/bulk_import/',
  dataType: 'json',
  data : {"shared_items": [{"entity_id":"253","position":1}, {"entity_id":"823","position":2}]}
});

परिणाम के रूप में रेल पार्सिंग बातें:

Parameters: {"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}}

जबकि यह (नोट: अब हम जावास्क्रिप्ट ऑब्जेक्ट को स्ट्रिंग कर रहे हैं और एक सामग्री प्रकार निर्दिष्ट कर रहे हैं, इसलिए रेल को पता चल जाएगा कि हमारी स्ट्रिंग को पार्स कैसे किया जाए):

$.ajax({
  type : "POST",
  url :  'http://localhost:3001/plugin/bulk_import/',
  dataType: 'json',
  contentType: 'application/json',
  data : JSON.stringify({"shared_items": [{"entity_id":"253","position":1}, {"entity_id":"823","position":2}]})
});

रेल में एक अच्छी वस्तु के परिणाम:

Parameters: {"shared_items"=>[{"entity_id"=>"253", "position"=>1}, {"entity_id"=>"823", "position"=>2}]}

रूबी 1.9.3 पर रेल 3 में मेरे लिए यह काम करता है।


1
यह रेल के लिए सही व्यवहार नहीं लगता है, यह देखते हुए कि JQuery से JSON प्राप्त करना रेल एप्लिकेशन के लिए एक बहुत ही सामान्य मामला है। क्या एक दोषपूर्ण तर्क है कि रेल इस तरह से व्यवहार क्यों करती है? ऐसा लगता है कि क्लाइंट-साइड जेएस कोड अनावश्यक रूप से हुप्स के माध्यम से कूद रहा है।
जेरेमी बर्टन

1
मुझे लगता है कि अपराधी के ऊपर के मामले में jQuery है। iirc jQuery Content-Typeके अनुरोध को सेट नहीं किया गया था application/json, लेकिन इसके बजाय एक HTML फॉर्म के रूप में डेटा भेज रहा था? इस पर वापस सोचना मुश्किल है। रेल Content-Typeसही मूल्य पर सेट होने के बाद, ठीक काम कर रहा था, और भेजे जा रहे डेटा वैध JSON था।
स्वजाक

3
नोट करना चाहते हैं न केवल @swajak ने ऑब्जेक्ट को सख्त किया बल्कि यह भी निर्दिष्ट कियाcontentType: 'application/json'
रोजर लैम

1
धन्यवाद @RogerLam, मैंने बेहतर वर्णन करने के लिए समाधान अपडेट किया है जो मुझे आशा है
swajak

1
@swajak: बहुत बहुत धन्यवाद! तुमने मेरा दिन बचाया, सच में! :)
कुलगर

12

थोड़ा पुराना सवाल है, लेकिन मैं आज खुद इस से लड़ता हूँ, और यहाँ जवाब मैं आया हूँ: मेरा मानना ​​है कि यह थोड़ा jQuery का दोष है, लेकिन यह केवल वही कर रहा है जो इसके लिए स्वाभाविक है। हालाँकि, मेरे पास वर्कअराउंड है।

निम्नलिखित jQuery के अजाक्स कॉल को देखते हुए:

$.ajax({
   type : "POST",
   url :  'http://localhost:3001/plugin/bulk_import/',
   dataType: 'json',
   data : {"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}]}

});

JQuery के मान पोस्ट कुछ इस तरह दिखाई देंगे (यदि आप अपने फायरबग-ऑफ-चॉइस में रिक्वेस्ट को देखते हैं) आपको ऐसा डेटा देगा जो दिखता है:

shared_items%5B0%5D%5Bentity_id%5D:1
shared_items%5B0%5D%5Bposition%5D:1

यदि आप CGI.unencode को प्राप्त करेंगे

shared_items[0][entity_id]:1
shared_items[0][position]:1

मेरा मानना ​​है कि ऐसा इसलिए है क्योंकि jQuery को लगता है कि आपके JSON में उन कुंजियों के रूप में तत्व नाम हैं, और यह उनके साथ ऐसा व्यवहार करना चाहिए जैसे कि आपके पास "उपयोगकर्ता [नाम]" नाम का एक फ़ील्ड था।

इसलिए वे आपके रेल एप्लिकेशन में आते हैं, रेल कोष्ठक को देखता है, और फ़ील्ड नाम की अंतरतम कुंजी ("1" जो कि jQuery "सहायक रूप से" जोड़ा गया है) को होल्ड करने के लिए एक हैश का निर्माण करता है।

वैसे भी, मैं इस व्यवहार के चारों ओर अपने ajax कॉल करके निम्नलिखित तरीके से मिला;

$.ajax({
   type : "POST",
   url :  'http://localhost:3001/plugin/bulk_import/',
   dataType: 'json',
   data : {"data": JSON.stringify({"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}])},
  }
});

जो jQuery को यह सोचने के लिए मजबूर करता है कि यह JSON एक ऐसा मान है जिसे आप पूरी तरह से पारित करना चाहते हैं, न कि एक जावास्क्रिप्ट ऑब्जेक्ट जिसे इसे लेना चाहिए और सभी कुंजी को फॉर्म फ़ील्ड नामों में बदलना चाहिए।

हालाँकि, इसका मतलब है कि चीजें रेल की तरफ से थोड़ी अलग हैं, क्योंकि आपको परमेसन [डेटा] में स्पष्ट रूप से JSON को डीकोड करने की आवश्यकता है।

किन्तु वह ठीक है:

ActiveSupport::JSON.decode( params[:data] )

TL; DR: तो, समाधान यह है: आपके jQuery.ajax () कॉल के डेटा पैरामीटर में, {"data": JSON.stringify(my_object) }JSON सरणी को jQuery में फीड करने के बजाय (जहां यह गलत अनुमान लगाता है कि आप इसके साथ क्या करना चाहते हैं, स्पष्ट रूप से करें।


बेहतर समाधान के लिए शीर्ष @swajak से नीचे है।
Event_jr

7

मैं बस इस मुद्दे पर रेल 4 के साथ भाग गया। स्पष्ट रूप से आपके प्रश्न का उत्तर देने के लिए ("रेल को अजीब हैश में सरणी क्यों बदल रहा है?"), एक्शन कंट्रोलर्स पर रेल गाइड की धारा 4.1 देखें :

मूल्यों की एक सरणी भेजने के लिए, मुख्य नाम के लिए "[]" वर्ग ब्रैकेट की एक खाली जोड़ी को जोड़ दें।

समस्या यह है, jQuery खाली वर्ग कोष्ठक के बजाय स्पष्ट सरणी सूचकांकों के साथ अनुरोध को प्रारूपित करता है। इसलिए, उदाहरण के लिए, भेजने के बजाय shared_items[]=1&shared_items[]=2, यह भेजता है shared_items[0]=1&shared_items[1]=2। रेल सरणी सूचकांकों को देखता है और सरणी सूचकांकों के बजाय हैश कुंजी के रूप में उनकी व्याख्या करता है, अनुरोध को एक अजीब रूबी हैश में बदल देता है { shared_items: { '0' => '1', '1' => '2' } }:।

यदि आपके पास क्लाइंट का नियंत्रण नहीं है, तो आप हैश को किसी सरणी में परिवर्तित करके सर्वर पर इस समस्या को ठीक कर सकते हैं। यहाँ है कि मैं यह कैसे किया:

shared_items = []
params[:shared_items].each { |k, v|
  shared_items << v
}

1

यदि आप मजबूत मापदंडों का उपयोग करते हैं तो निम्न विधि मददगार हो सकती है

def safe_params
  values = params.require(:shared_items)
  values = items.values if items.keys.first == '0'
  ActionController::Parameters.new(shared_items: values).permit(shared_items: [:entity_id, :position]).require(:shared_items)
end

0

क्या आपने करने पर विचार किया है parsed_json = ActiveSupport::JSON.decode(your_json_string)? यदि आप सामान भेज रहे हैं तो आप .to_jsonडेटा को क्रमबद्ध करने के लिए उपयोग कर सकते हैं ।


1
हां माना जाता है, लेकिन यह जानना चाहता था कि क्या रेल में ऐसा करने का कोई "सही तरीका" है, बिना मैन्युअल रूप से एन्कोड / डिकोड किए बिना।
अल्दललगंडे

0

क्या आप केवल JSON स्ट्रिंग को रेल नियंत्रक कार्रवाई में लाने की कोशिश कर रहे हैं?

मुझे यकीन नहीं है कि रेल हैश के साथ क्या कर रही है, लेकिन आप समस्या के आसपास हो सकते हैं और एक जावास्क्रिप्ट (JSON ऑब्जेक्ट (जैसे JSON स्ट्रिंग के विपरीत) बनाकर और अपने Ajax के डेटा पैरामीटर के माध्यम से भेजकर अधिक भाग्य प्राप्त कर सकते हैं कहते हैं।

myData = {
  "shared_items":
    [
        {
            "entity_id": "253",
            "position": 1
        }, 
        {
            "entity_id": "823",
            "position": 2
        }
    ]
  };

यदि आप इसे अजाक्स के माध्यम से भेजना चाहते हैं तो आप कुछ इस तरह से करेंगे:

$.ajax({
    type: "POST",
    url: "my_url",    // be sure to set this in your routes.rb
    data: myData,
    success: function(data) {          
        console.log("success. data:");
        console.log(data);
    }
});

ऊपर ajax स्निपेट के साथ ध्यान दें, jQuery डेटाटाइप पर एक बुद्धिमान अनुमान लगाएगा, हालांकि आमतौर पर स्पष्ट रूप से निर्दिष्ट करना अच्छा है।

किसी भी तरह से, अपने नियंत्रक क्रिया में, आप JSON वस्तु को पारस हैश के साथ पास कर सकते हैं, अर्थात

params[:shared_items]

उदाहरण के लिए, यह क्रिया आपकी जसन ऑब्जेक्ट को आप पर थूक देगी:

def reply_in_json
  @shared = params[:shared_items]

  render :json => @shared
end

धन्यवाद, लेकिन यही मैं अभी कर रहा हूं (अपडेट देखें) और यह काम नहीं करता है।
अल्दललगंडे

0

का प्रयोग करें रैक jQuery-पैरामीटर मणि (अस्वीकरण: मैं लेखक हूँ)। यह पूर्णांक कुंजियों के साथ हैश बन रहे सरणियों के आपके मुद्दे को ठीक करता है।


लिंक डालने के बजाय कुछ कोड स्निपेट प्रदान करना बेहतर है
विकासदीप सिंह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.