【问题标题】:Stopping a string being encoded within a hash Ruby on Rails停止在哈希 Ruby on Rails 中编码的字符串
【发布时间】:2020-07-29 11:40:42
【问题描述】:

我试图不对哈希中的字符串进行 jsonify。它已经被逃脱了。

了解 PORO 的处理方式是覆盖 as_json。所以我将字符串包裹在另一个对象中。但是当我返回对象时,我只处理一个导致stack level too deep 的字符串。当我返回已经编码的字符串时,它显然会尝试转义它。 activesupport-6.0.3.2/lib/active_support/json/encoding.rb

      def jsonify(value)
        case value
        when String
          EscapedString.new(value)
        when Numeric, NilClass, TrueClass, FalseClass
          value.as_json
        when Hash
          Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
        when Array
          value.map { |v| jsonify(v) }
        else
          jsonify value.as_json
        end
      end

我可以做的是猴子补丁上面的方法来接受我已经包装了字符串的类并且什么都不做。

我猜另一种选择是将 JSON 字符串解析回散列并让它遵循正常程序。但这会对我们的表现造成太大影响。

所以我的问题是,有没有更优雅的方法来告诉 Rails 在遇到指定对象时什么都不做。

编辑:

我正在使用这个已经 jsonified 的字符串,例如:

{foo: MyStringJsonWrapper.new('{"bar":"foobar"}')}.to_json

【问题讨论】:

  • 如何在控制器中调用它?请记住,当您执行render json: @stuff 时,会调用as_json。您应该将此方法命名为as_json
  • 嗨@LesNightingill 我这样称呼它:{foo: MyStringJsonWrapper.new('{"bar":"foobar"}')}.to_json

标签: ruby-on-rails json ruby ruby-on-rails-6


【解决方案1】:

我在文件activesupport-6.0.3.2/lib/active_support/json/encoding.rb 中四处查看,发现您可以配置用于执行json 编码的类。当前是 JSONGemEncoder,包含在该类中。

所以我创建了自己的课程:

class MyJSONEncoder < ActiveSupport::JSON::Encoding::JSONGemEncoder
  class AlreadyEscapedString < String
    def to_json(*)
      self
    end
  end

  private

  def jsonify(value)
    if value.is_a?(AlreadyEncodedStringWrapper)
      AlreadyEscapedString.new(value.already_jsonified)
    else
      super
    end
  end
end

class AlreadyEncodedStringWrapper
  attr_accessor :already_jsonified

  def initialize already_jsonified
    @already_jsonified = already_jsonified
  end

  def as_json(options = {})
    self
  end
end

存在AlreadyEscapedString 的额外类以覆盖EscapedString(在同一编码类中找到)的行为,但什么也不做。

然后设置:

ActiveSupport.json_encoder = MyJSONEncoder

例子:

jsonified_hash = {foobar: "barbaz"}.to_json

already_encoded_string = AlreadyEncodedStringWrapper.new(jsonified_hash)

{foo: already_encoded_string}.to_json
=> "{\"foo\": {\"foobar\": \"barbaz\"}}"

【讨论】:

    猜你喜欢
    • 2011-09-02
    • 2014-04-09
    • 2014-05-14
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 2015-08-25
    • 2013-08-21
    • 2012-12-18
    相关资源
    最近更新 更多