2011-02-25 7 views
18

मेरी नियंत्रक में, निम्न काम करता है (प्रिंट "ओके")JSON एन्कोडिंग को गलत तरीके से भाग निकले (रेल 3, रूबी 1.9.2)

puts obj.inspect 

लेकिन यह नहीं करता है (renders "ठीक है \ u00e9")

render :json => obj 

स्पष्ट रूप से to_json विधि यूनिकोड वर्णों से बच निकलती है। क्या इसे रोकने के लिए कोई विकल्प है?

+0

यह डेटाबेस समस्या नहीं है। –

उत्तर

14

आप स्रोत के माध्यम से खुदाई, तो आप अंत में ActiveSupport::JSON::Encoding के लिए आते हैं और escape विधि होगी:

def escape(string) 
    if string.respond_to?(:force_encoding) 
    string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY) 
    end 
    json = string. 
    gsub(escape_regex) { |s| ESCAPED_CHARS[s] }. 
    gsub(/([\xC0-\xDF][\x80-\xBF]| 
      [\xE0-\xEF][\x80-\xBF]{2}| 
      [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s| 
    s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&') 
    } 
    json = %("#{json}") 
    json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding) 
    json 
end 

विभिन्न gsub कॉल के लिए मजबूर कर रहे हैं गैर- ASCII UTF-8 \uXXXX अंकन है कि आप देख रहे हैं करने के लिए । हेक्स एन्कोडेड यूटीएफ -8 जेएसओएन को संसाधित करने वाली किसी भी चीज़ के लिए स्वीकार्य होना चाहिए, लेकिन यदि आवश्यक हो तो \uXXXX नोटेशन कच्चे यूटीएफ -8 को परिवर्तित करने के लिए आप हमेशा जेएसओएन (या संशोधित JSON एस्केपर में बंदर पैच) को पोस्ट-प्रोसेस कर सकते हैं।

मैं इस बात से सहमत हूं कि JSON को 7 बिट-क्लीन होने के लिए मजबूर करना थोड़ा बोगस है लेकिन वहां आप जाते हैं।

संक्षिप्त उत्तर: नहीं।

9

यह सही एन्कोडिंग है। JSON की आवश्यकता नहीं है यूनिकोड वर्णों से बचने के लिए, लेकिन जेएसओएन पुस्तकालयों के लिए उत्पादन में उत्पादन करना आम है जिसमें पारगमन में किसी भी संभावित एन्कोडिंग समस्याओं से बचने के लिए केवल 7-बिट ASCII वर्ण होते हैं।

कोई भी JSON दुभाषिया उस स्ट्रिंग का उपभोग करने और मूल को पुन: पेश करने में सक्षम होगा। इसे क्रिया में देखने के लिए, बस अपने ब्राउज़र के स्थान पट्टी में javascript:alert("ok\u00e9") टाइप करें।

+0

यह लड़का सही है: thumbsup: – freedrull

33

\ uXXXX कोड utf-8 के लिए वापस सेट करने के लिए:

json_string.gsub!(/\\u([0-9a-z]{4})/) {|s| [$1.to_i(16)].pack("U")} 
+0

ने मेरा जेसन एन्कोडिंग मुद्दा हल किया, बहुत बहुत धन्यवाद – Fizz

21

आप बंदर विधि Muu ने उल्लेख बहुत छोटा है पैचिंग से रोक सकते हैं। निम्नलिखित को कॉन्फ़िगर/प्रारंभकर्ता/patches.rb (या समान फ़ाइल को पैचिंग सामग्री के लिए उपयोग किया जाता है) में रखें और परिवर्तन को प्रभावित करने के लिए अपनी रेल प्रक्रिया को पुनरारंभ करें।

module ActiveSupport::JSON::Encoding 
    class << self 
    def escape(string) 
     if string.respond_to?(:force_encoding) 
     string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY) 
     end 
     json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] } 
     json = %("#{json}") 
     json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding) 
     json 
    end 
    end 
end 

सलाह दी कोई गारंटी नहीं कि पैच ActiveSupport के भविष्य के संस्करणों के साथ काम करेंगे यह है कि। इस पोस्ट को लिखते समय उपयोग किया गया संस्करण 3.1.3 है।

+0

जितना मुझे इससे नफरत है, उसने जेएसओएन मुद्दों में पूरी तरह से अपने इमोजी को हल किया। धन्यवाद! –

+0

अभी भी रेल 3.1.6 में एक समस्या है, और यह पैच अभी भी इसे ठीक करता है। रेल टीम को वास्तव में इस समस्या को उनके JSON एन्कोडिंग में ठीक करने की आवश्यकता है; इमोजी कुछ ऐसा नहीं है जो दूर जा रहा है, खासकर अब यह यूनिकोड मानक का हिस्सा है। – poetmountain

+0

इसे कम डरावनी समाधान के लिए देखें: http://stackoverflow.com/questions/683989/how-do-you-deal-with-the-conflict-between-activesupportjson-and-the-json-gem/3285570#3285570 – vish

0

मुझे इस समस्या को हल करने का एक बहुत ही मुश्किल तरीका है। खैर, अगर to_json आपने सही कोड के लिए अनुमति नहीं दी है, तो आप सीधे लिखने की कोशिश कर सकते हैं:

render text: tags 

render json: tags या render json: tags.to_json हमेशा ऑटो हस्तांतरण एन्कोडिंग शैली, लेकिन अगर आप render text:tags उपयोग करते हैं, तो स्ट्रिंग होगा जैसा रहना है और मुझे लगता है कि jQuery अभी भी डेटा को पहचान सकता है।

9

वर्ण Rails2.3.11/Ruby1.8 में अन्य तरीकों के साथ यूनिकोड में भाग नहीं कर रहे थे तो मैं निम्नलिखित प्रयोग किया है:

render :json => JSON::dump(obj) 
+0

हां, यह 1.8 और रेल 2.3 में काम करता है। अच्छा था। – user589473

2

प्रस्तुत करना: json अगर यह एक स्ट्रिंग नहीं है वस्तु पर .to_json कॉल करेंगे।आप ऐसा करके इस समस्या से बचने कर सकते हैं:

render :json => JSON.generate(obj) 

यह द्वारा सीधे एक स्ट्रिंग पारित और इसलिए ActiveSupport के to_json करने के लिए कॉल से बचने जाएगा।

class Foo < ActiveRecord::Base 
    def to_json(options = {}) 
    JSON.generate(as_json) 
    end 
end 

और अगर आप ActiveModelSerializers उपयोग करते हैं, तो आप इस समस्या to_json अधिभावी द्वारा हल कर सकते हैं:

एक और दृष्टिकोण वस्तु आप serializing कर रहे हैं पर to_json ओवरराइड करने के लिए है, तो उस स्थिति में, आप कुछ की तरह कर सकता है हो सकता है आपके सीरियललाइज़र में:

# controller 
respond_with foo, :serializer => MySerializer 

# serializer 
attributes :bar, :baz 

def to_json(options = {}) 
    JSON.generate(serializable_hash) 
end 
संबंधित मुद्दे