كيف تتعامل مع التعارض بين ActiveSupport::JSON وجوهرة JSON؟
-
22-08-2019 - |
سؤال
أنا في حيرة من هذه المشكلة.
ActiveSupport::JSON
يحدد to_json
على كائنات أساسية مختلفة وكذلك جوهرة JSON.ومع ذلك، فإن التنفيذ ليس هو نفسه - إصدار ActiveSupport يأخذ الوسائط بينما إصدار JSON Gem لا يأخذها.
لقد قمت بتثبيت جوهرة تتطلب جوهرة JSON وتعطل تطبيقي.المشكلة هي أنني أستخدم to_json
في وحدة التحكم التي تُرجع قائمة بالكائنات، لكني أريد التحكم في السمات التي يتم إرجاعها.
عندما يفعل الكود في أي مكان في نظامي require 'json'
أحصل على رسالة الخطأ هذه:
TypeError: wrong argument type Hash (expected Data)
لقد جربت بعض الأشياء التي قرأتها عبر الإنترنت لإصلاحها، لكن لم ينجح أي شيء.انتهى بي الأمر بإعادة كتابة الجوهرة لاستخدامها ActiveSupport::JSON.decode
بدلاً من JSON.parse
.
يعمل هذا ولكنه غير مستدام... لا يمكنني تشعب الجواهر في كل مرة أرغب فيها في استخدام جوهرة تتطلب جوهرة JSON.
تحديث: أفضل حل لهذه المشكلة هو الترقية إلى Rails 2.3 أو أعلى، مما أدى إلى حل المشكلة.
المحلول
تحديث ينطبق هذا الإصلاح فقط على Rails <2.3.وكما يذكر جايلز أدناه، فقد قاموا بإصلاح هذه المشكلة في الإصدار 2.3 داخليًا باستخدام نفس التقنية تقريبًا.لكن احذر من محاولة json Gem السابقة للتوافق مع Rails (json/add/rails
), والتي، إذا لزم الأمر صراحة سوف كسر كل شيء من جديد.
هل تقصد require 'json'
البيان نفسه يثير هذا الاستثناء؟أو تقصد عند الاتصال @something.to_json(:something => value)
تحصل على الخطأ؟الأخير هو ما أتوقعه، إذا كانت لديك مشكلة في طلب جوهرة JSON، فأنا لست متأكدًا مما يحدث.
لقد واجهت للتو هذه المشكلة مع جوهرة oauth.في حالتي، لا يوجد تعارض حقيقي، لأن جوهرة المصادقة لا تعتمد عليها to_json
تطبيق.لذلك تكمن المشكلة في أن JSON يحجب إعلانات ActiveSupport.لقد قمت بحل هذه المشكلة ببساطة عن طريق طلب json قبل تحميل ActiveSupport.وضع
require 'json'
داخل Rails::Initializer
لقد قام بالخدعة (على الرغم من عدم وضعها بعد الكتلة).
يتيح ذلك لـ ActiveSupport التغلب على تطبيق JSON الافتراضي بدلاً من ذلك.
الآن إذا كنت تستخدم جوهرة تعتمد فعليًا على تطبيق JSON لـ to_json
فأنت فوق الخور.هذا بالتأكيد هو أسوأ ما في البرمجة الوصفية، وأود أن أدعو مطوري Rails وJSON Gem إلى حل هذا التعارض، على الرغم من أنه سيكون مؤلمًا لأنه سيتعين على أحدهما أو الآخر كسر التوافق مع الإصدارات السابقة.
على المدى القصير، قد يتمكن مؤلفو الأحجار الكريمة من سد الفجوة من خلال دعم كلا التطبيقين.يعد هذا ممكنًا إلى حد ما اعتمادًا على كيفية استخدام الجوهرة لهذه الطريقة.أسوأ السيناريوهات هو الشوكة الرسمية (أي. gem
و gem-rails
).
نصائح أخرى
تحديث:حتى مع الإصدار 3.2 من Rails، تظل نفس المشكلة دون حل.هذا هو الاختراق السيئ لتحميل جوهرة json بالقوة والكتابة فوقها.
في نهاية المطاف، انتهى بي الأمر بالكود التالي، لتجاوز ActiveSupport بالكامل to_json
بالكامل.ضعها في config/initializers/patches.rb
, ، ويمكنك القيام به {}.jsonize
أو [].jsonize
لإنشاء سلسلة JSON.لا يتعارض مع أي شيء، مضمونة.
# Undo the effect of 'active_support/core_ext/object/to_json'
require 'json'
[Object, Array, Hash].each do |klass|
klass.class_eval <<-RUBY, __FILE__, __LINE__
def jsonize(options = nil)
::JSON.generate self, :quirks_mode => true
end
RUBY
end
الأسطر الثمانية من التعليمات البرمجية تجعل تطبيقك 50 مرة أسرع لتشفير JSON.ربما تريد أن تفعل الشيء نفسه.:)
لقد كنت أواجه مشكلة مماثلة حتى الإصدار 2.3.8 من Rails.
المشكلة هي ActiveSupport::JSON.backend = 'JSONGem'
هو حل غير مؤكد وما زلت بحاجة إلى استبدال بعض برامج التشفير بنفسك.(تحذير:بالنسبة إلى Rails 3.x، الذي يستخدم MultiJson، يجب أن يكون كذلك ActiveSupport::JSON.backend = :json_gem
على الأقل، أو سيكون بصمت عدم المرجع.)
في حالتي، كنت بحاجة إلى الكتابة String#to_json
لأن JSON Gem 1.4.3 أفضل من حيث أنه لا يقوم بتشفير أحرف UTF8 غير ascii ولكن صالحة بشكل أعمى في شكل "\uXXXX"
عندما لا يكون ذلك ضروريًا، حتى تحصل على بايتات أقصر (جيدة للتسلسل) ونتائج سهلة القراءة ("日本語"
يبدو أكثر جنسية لعيني من "\u65e5\u672c\u8a9e"
).
هذا هو التصحيح القردي الذي كنت أستخدمه - ضع الكود التالي فيه config/initializers/patches.rb
module ActiveSupport
module JSON
module Encoding
class << self
def escape(string)
::JSON.generate([string])[1..-2]
end
end
end
end
end
وأنت حر في الاستخدام to_json
على أي شيء - السلسلة والمصفوفة والتجزئة.
بعد مقاومة هذا لفترة من الوقت..لقد وجدت أن الحل الأبسط هو:
if defined?(ActiveSupport::JSON)
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
klass.class_eval do
def to_json(*args)
super(args)
end
def as_json(*args)
super(args)
end
end
end
end
ضع ذلك في أي مكان بعد تحميل الدعم النشط..
أنا متأكد من أنهم أصلحوا هذه المشكلة في الإصدار 2.3 ولكن لا أتذكر كيف.
في حالتي، وإن كانت فريدة من نوعها، كان لدي تطبيق Ruby (غير تابع لـ Rails) والذي قام بالفعل بتحميل تطبيق Rails (من تحميل config/environment.rb) بالإضافة إلى بعض الأحجار الكريمة التي تشير إلى json.لقد سبب لي هذا صداعًا كبيرًا نظرًا لحقيقة أنني لم أتمكن ببساطة من تغيير ملف بيئة تطبيق Rails.rb.انتهى بي الأمر إلى تفرع عدد من الأحجار الكريمة من أجل جعل json يعمل دون رفع خطأ TypeError المخيف:وسيطة خاطئة اكتب رسالة التجزئة (البيانات المتوقعة).
لقد حالفني بعض الحظ في هذا الحل، وهو عكس تمامًا إجابة مجتمع ويكي أعلاه ...http://blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.htmlالذي يدعو الاتصال بشكل أساسي يتطلب "Active_support"قبل تتطلب "json"
كانت هذه هي الطريقة الوحيدة التي تمكنت من إنجاح الأمر، وصدقوني لقد جربت كل شيء على مدار عدة أشهر.
لم أجربه بعد، ولكن يبدو أن Rails 2.3.3 يمنحك بعض التحكم:
ActiveSupport::JSON.backend = 'JSONGem'