如何在不退出反斜杠的情况下在Rails中输出JSON

我需要以某种不寻常的格式为客户输出一些JSON。 我的应用程序是用Rails 5编写的。

期望的JSON:

{
  "key": "/Date(0000000000000)/"
}

时间戳值需要在字符串的开始和结尾都有一个/ 。 据我所知,这似乎是.NET服务中常用的一种格式。 我卡住试图让斜线正确输出。

我通过一个控制器操作将问题简化为了一个vanilla Rails 5应用程序。 迄今为止,我能想到的所有逃生排列都失败了。

def index
  render json: {
    a: '/Date(0000000000000)/',
    b: "/Date(0000000000000)/",
    c: '/Date(0000000000000)/',
    d: "/Date(0000000000000)/"
  }
end

其中输出以下内容:

{
    "a": "/Date(0000000000000)/",
    "b": "/Date(0000000000000)/",
    "c": "/Date(0000000000000)/",
    "d": "/Date(0000000000000)/"
}

为了讨论的缘故,假设格式不能被改变,因为它是由第三方控制的。

我上传了一个测试应用程序给Github来展示问题。 https://github.com/gregawoods/test_app_ignore_me


经过与同事的一些头脑风暴(感谢@TheZanke)后,我们找到了一个可以与原生Rails JSON输出结合使用的解决方案。

警告:此代码覆盖ActiveSupport中的一些核心行为。 使用风险自负,并应用适当的单元测试!

我们将其跟踪到ActiveSupport中的JSON编码。 所有字符串最终都通过ActiveSupport::JSON.encode进行编码。 我们需要找到一种方法来短路该逻辑并简单地返回未编码的字符串。

首先我们扩展了这里找到的EscapedString#to_json方法。

module EscapedStringExtension
  def to_json(*)
    if starts_with?('noencode:')
      ""#{self}"".gsub('noencode:', '')
    else
      super
    end
  end
end

module ActiveSupport::JSON::Encoding
  class JSONGemEncoder
    class EscapedString
      prepend EscapedStringExtension
    end
  end
end

然后在控制器中添加一个noencode:标志给json散列。 这告诉我们的to_json版本不要做任何额外的编码。

def index
  render json: {
     a: '/Date(0000000000000)/',
     b: 'noencode:/Date(0000000000000)/',
   }
end

渲染输出显示, b为我们提供了我们想要的东西,而a保留了标准的行为。

$ curl http://localhost:3000/sales/index.json
{"a":"/Date(0000000000000)/","b":"/Date(0000000000000)/"}

默想这个:

Ruby在双引号和单引号字符串中使用相同的正斜杠。

"/"   # => "/"
'/'   # => "/"

在双引号字符串"/"表示正在转义下面的字符。 由于/没有转义的等价物,它会导致一个正斜杠:

"/"  # => "/"

在所有情况下的单引号字符串中,只有一个意味着存在反斜杠,后跟字符的字面值。 这种情况是你想表示一个反斜杠本身:

'/'  # => "/"

"/" # => "/"
'/' # => "/"

学习这是关于在语言中处理字符串最令人困惑的部分之一,这不仅限于Ruby,它是编程早期的事情。

了解以上内容:

require 'json'

puts JSON[{ "key": "/value/" }] 
puts JSON[{ "key": '/value/' }]
puts JSON[{ "key": '/value/' }]

# >> {"key":"/value/"}
# >> {"key":"/value/"}
# >> {"key":"/value/"}

你应该能够更好地理解你在结果和上面的JSON输出中看到的内容。

我认为这个规则最初是为C创建的,所以“C中的转义序列”可能会有所帮助。


嗨,我认为这是最简单的方法

.gsub("/",'//').gsub('/','')

用于输入{:key=>"/Date(0000000000000)/"} (打印)

第一个gsub会做{"key":"//Date(0000000000000)//"}

第二会让你

{"key":"/Date(0000000000000)/"}

如你所需

链接地址: http://www.djcxy.com/p/47929.html

上一篇: How to output JSON in Rails without escaping back slashes

下一篇: How to safely embed JSON with </script> in HTML document?