2011-05-25 14 views
43

मैं उस मॉडल के लिए डिफ़ॉल्ट JSON क्रमबद्धता का उपयोग कर रहा हूं जिसमें कई दशमलव और पूर्णांक गुण हैं। एक उदाहरण परिणाम है:दशमलव के जेएसओएन सीरियलाइजेशन उद्धरण

{ "user": { "id": 1234, "rating": "98.7" } } 

सूचना "रेटिंग" का मान-पीछे उद्धरण चिह्न के अलावा। इससे deserialization लाइब्रेरी का कारण बनता है जिसका उपयोग मैं इन्हें स्ट्रिंग्स (दशमलव के बजाए) के रूप में गलत तरीके से करने के लिए कर रहा हूं। क्या रेलों को सभी दशमलव के लिए उद्धरणों का उपयोग नहीं करने के लिए सेट किया जा सकता है?

संपादित करें:

मैं ऑन रेल्स 3.0.7 और रूबी 1.9.2 कि अगर एक फर्क नहीं पड़ता।

संपादित करें:

टर्मिनल:

rails g model user rating:decimal 
rake db:migrate 

कंसोल:

user = User.create(rating: 98.7) 
user.to_json 
+0

कुछ अतिरिक्त कोड शामिल करें। मैं इसे पुन: उत्पन्न करने में असमर्थ था। –

+0

@ पैन मैंने एक उदाहरण जोड़ा है। –

उत्तर

26

इस रेल 4.0 जो कि आप अपने BigDecimal क्रमबद्धता प्राथमिकता का उल्लेख कर सकते हैं विकल्प ActiveSupport.encode_big_decimal_as_string है तो के लिए बदल गया है। See issue 6033

इस दौरान, आप तर्क 6033 में पेश किया का ज्ञान है और आप 4 की तुलना में एक रेल संस्करण कम चला रहे हैं।0 आप नीचे दिए गए

require 'bigdecimal' 

class BigDecimal 
    def as_json(options = nil) #:nodoc: 
    if finite? 
     self 
    else 
     NilClass::AS_JSON 
    end 
    end 
end 

यह Rabl BigDecimal के रूप में जमा डॉलर की राशि के लिए तार बाहर पंप के साथ अपने मुद्दों को हल कर के रूप में बंदर पैच BigDecimal कर सकते हैं।

+0

अद्यतन के लिए धन्यवाद! मैं थोड़ा में इस मुद्दे को देखा नहीं है लेकिन यह पता करने के लिए यह 4.0 –

+0

कोई समस्या नहीं है में अनुकूलित किया जा सकता है। बस सोचा कि मैं इस समाधान को Google पर राउंड करने वाले लोगों के लिए बाहर रखूंगा! – toxaq

+3

दुर्भाग्य से 'encode_big_decimal_as_string' विकल्प रेल 4.1 में फिर से मान्य नहीं है। – Jazz

39

केवल "सुरक्षित" जिस तरह से भाषा बी को भाषा एक से दशमलव के हाथ एक स्ट्रिंग का उपयोग करने के लिए है । यदि आपके जेसन में "rating": 98.79999999999999 है तो इसे शायद आपके जावास्क्रिप्ट रनटाइम द्वारा 98.79999999999998 में परिवर्तित कर दिया जाएगा।

एक BigDecimal स्वाभाविक रूप से एक JSON संख्या के रूप में प्रतिनिधित्व होगा:

BigDecimal as_json दस्तावेज़ देखें। अधिकांश पुस्तकालय, हालांकि, गैर-पूर्णांक JSON संख्या सीधे फ़्लोट के रूप में पार्स करते हैं। उन पुस्तकालयों का उपयोग करने वाले ग्राहक सामान्य रूप से एक गलत संख्या प्राप्त करते हैं और मैन्युअल रूप से JS12 कोड के साथ स्ट्रिंग का निरीक्षण करने के लिए मैन्युअल रूप से से पुनर्प्राप्त करने के लिए कोई तरीका नहीं मिलता है।

यही कारण है कि एक JSON स्ट्रिंग वापस आती है। JSON शाब्दिक, दूसरे छोर अनुबंध से जानता है कि डेटा एक BigDecimal माना जाता है संख्यात्मक नहीं है, लेकिन यह अभी भी बाद प्रक्रिया स्ट्रिंग के लिए मौका है और वास्तविक मूल्य मिलता है।

यदि आप रेल को इन्हें उद्धृत न करने के लिए बाध्य करना चाहते हैं, तो आप बंदर-पैच बिगडेसिमल (रेल source देखें) देख सकते हैं।

# not needed: to compare with the Numeric implementation 
class Numeric 
    def as_json(options = nil) self end #:nodoc: 
    def encode_json(encoder) to_s end #:nodoc: 
end 

class BigDecimal 
    def as_json(options = nil) self end 
    def encode_json(encoder) to_s end #:nodoc: 
end 
+0

धन्यवाद मार्सेल। क्या मुझे मुद्राओं और वॉल्यूम के भंडारण के लिए 'दशमलव' प्रकार का उपयोग नहीं करना चाहिए? मुझे नहीं लगता कि मैं कभी भी गंभीर गोल करने वाली त्रुटियों को मार दूंगा। –

+1

सिद्धांत में आपको चाहिए। लेकिन मैं मुद्राओं के बारे में सबसे वास्तविक दुनिया की समस्याओं के लिए दशमलव अधिक पूर्णांकों ('money' मणि एक' xyz_cents' कॉलम में पूर्णांकों का उपयोग करता है) पसंद करेंगे। –

9

अगर आप ActiveModel :: Serializer उपयोग कर रहे हैं तो आप भी to_f का उपयोग प्रकार फ्लोट करने के लिए दशमलव से रूपांतरण के लिए मजबूर कर सकते हैं। वह भी आपके लिए उद्धरण को ट्रिम कर देगा!

तो आपके ऑब्जेक्ट सीरिएलाइज़र क्लास में। ऐसा

def rating 
    self.rating.to_f 
end 
+3

क्या यह पहली जगह बिगडिसीमल का उपयोग करने के बिंदु को पूरी तरह से बर्बाद नहीं करता है, हालांकि? यदि मैं एक एपीआई एंडपॉइंट पर मौद्रिक मूल्य पारित करने की कोशिश कर रहा हूं, उदाहरण के लिए, यह दृष्टिकोण फ़्लोट्स के निहित सभी राउंडिंग त्रुटियों को दोबारा पेश करेगा। यदि यह डेटा को विचलित करता है, तो इसे समाधान नहीं माना जाना चाहिए। – Jazz

+1

यह मेरे लिए "सिस्टमस्टैक त्रुटि (ढेर स्तर बहुत गहरा)" अपवाद का कारण बनता है। Object.rating.to_f का उपयोग ठीक काम करता है। –

0
रेल के साथ

5 encode_big_decimal_as_string (यह इसलिए कोई वहाँ आश्चर्य पदावनत किया गया था) काम नहीं करता।

आप अपने आवेदन करने के लिए JBuilder जोड़ देते हैं तो

# Gemfile 
gem 'jbuilder', '~> 2.5' 

तो बस एक json का मानना ​​है कि सिर्फ दृश्य के लिए एक नाव के लिए दशमलव डाले बनाते हैं, आप सुनहरा होना चाहिए।

# app/views/yourmodel/index.json.jbuilder 
json.array! @yourmodels do |yourmodel| 
    json.attributethatisadecimal yourmodel.attributethatisadecimal.to_f 
end 

यह मेरे लिए अच्छी तरह से काम - एक कुछ अधिक परिश्रम (क्योंकि आप JBuilder करने के लिए अपने मॉडल मैप करने के लिए है) लेकिन इस दृष्टिकोण बहुत साफ लगता है।

संबंधित मुद्दे