2

好先生。如何强制 request.body (或任何其他非 JSON 字符串)以漂亮的多行 JSON 或 yaml 样式打印出来?

我已经看到了将此类字符串转换为真实 JSON 的奇特方法,但希望避免使用另一种方法。

  def request_token_from_google
    uri = URI.parse('https://www.googleapis.com/oauth2/v3/token')
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    request = Net::HTTP::Post.new(uri.request_uri)
    request.set_form_data(self.to_params)
    puts "request body is"
    puts request.body.to_yaml # doesn't work
    puts request.body.to_json # doesn't work
    http.request(request)
  end
4

1 回答 1

2

这个问题:

ap "request body is #{request.body.to_json}"

...而您的其他尝试是您正在尝试漂亮地打印已经是字符串的东西。awesome_print(以及inspect它们的同类)的目的是获取一个具有某种结构的对象并将其打印出来,以便您可以看到它的结构,但是字符串没有结构——它只是一个字符、一个字符、一个字符。当您给 awesome_print 一个字符串时,"request body is {"foo":...它无法知道“is”之后的部分有什么特别之处。

如果您有一个具有结构的对象,解决方案是将其直接提供给 awesome_print:

puts "request body is:"
ap my_hash_or_array

不幸的是,在这种情况下它不会有帮助,因为request.body它也只是一个字符串——它是表单编码的数据,就像这样(从Wikipedia窃取):

Name=Jonathan+Doe&Age=23&Formula=a+%2B+b+%3D%3D+13%25%21

就像"request body is..."示例一样,awesome_print 无法知道这有什么特别之处。您可以做的一件非常简单的事情就是在每个键/值对之间添加一个换行符:

body = "Name=Jonathan+Doe&Age=23&Formula=a+%2B+b+%3D%3D+13%25%21"

puts "Request body is:"
puts body.gsub("&", "\n  &")
# => Request body is:
#    Name=Jonathan+Doe
#      &Age=23
#      &Formula=a+%2B+b+%3D%3D+13%25%21

这样做的缺点是值仍然是百分比编码的,正如您在Formula. 如果这是一个问题,您可以使用CGI.parseor来解析表单数据Rack::Utils.parse_query,这两种方法都可以在 Rails 中使用。它们都返回一个哈希值,您可以将其提供给 awesome_print,但格式略有不同(CGI 将所有值作为数组返回,Rack::Utils 仅在它们采用“数组”格式时才会这样做,例如foo[]=1&foo[]=2)。这是 Rack::Utils (你只需要想象输出是彩色的):

puts "Request body is:"
ap Rack::Utils.parse_query(body)
# => Request body is:"
#    {
#           "Name" => "Jonathan Doe",
#            "Age" => "23",
#        "Formula" => "a + b == 13%!"
#    }

最后,一些不请自来的建议:putsand ap,它写入 STDOUT,在开发中往往可以正常工作,因为 Rails 的记录器也在写入 STDOUT,因此您可以puts在与 Rails 服务器日志相同的终端窗口中看到输出。然而,在生产中,写入 STDOUT 的数据可能不会写入任何地方的文件,即使是这样,如果您Rails.logger在某个时候更改配置,ap的输出可能仍会发送到其他地方。您可能想要的是使用 Rails 的 logger 而不是putsor ap,因此您可以确保所有输出都到同一个地方。幸运的是,awesome_printawesome_inspect为每个对象添加了一个方法,该方法返回您在使用时看到的漂亮字符串ap,因此您仍然可以将 awesome_print 与Rails.logger

body_inspect = Rack::Utils.parse_query(body).awesome_inspect
Rails.logger.info("Request body is:\n#{body_inspect}")
于 2015-06-04T15:38:15.410 回答