如何在RubyonRails中”漂亮地”格式化JSON输出?

如何在RubyonRails中”漂亮地”格式化JSON输出?

How can I “pretty” format my JSON output in Ruby on Rails?

我希望RubyonRails中的JSON输出是"漂亮的"或格式良好的。

现在,我给to_json打电话,我的json都在一条线上。有时,很难看到JSON输出流中是否存在问题。

有没有方法配置或方法使我的JSON"漂亮"或在Rails中很好地格式化?


使用pretty_generate()函数,该函数内置于更高版本的JSON中。例如:

1
2
3
require 'json'
my_object = { :array => [1, 2, 3, { :sample =>"hash"} ], :foo =>"bar" }
puts JSON.pretty_generate(my_object)

你得到:

1
2
3
4
5
6
7
8
9
10
11
{
 "array": [
    1,
    2,
    3,
    {
     "sample":"hash"
    }
  ],
 "foo":"bar"
}

由于使用了机架中间件和Rails3,您可以为每个请求输出漂亮的JSON,而无需更改应用程序的任何控制器。我已经编写了这样的中间件片段,并且在浏览器和curl输出中很好地打印了JSON。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class PrettyJsonResponse
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    if headers["Content-Type"] =~ /^application\/json/
      obj = JSON.parse(response.body)
      pretty_str = JSON.pretty_unparse(obj)
      response = [pretty_str]
      headers["Content-Length"] = pretty_str.bytesize.to_s
    end
    [status, headers, response]
  end
end

上面的代码应该放在Rails项目的app/middleware/pretty_json_response.rb中。最后一步是在config/environments/development.rb中注册中间件:

1
config.middleware.use PrettyJsonResponse

我不建议在production.rb中使用它。JSON修复可能会降低生产应用程序的响应时间和吞吐量。最终,可能会引入额外的逻辑,例如"x-pretty-json:true"头,以根据需要触发手动curl请求的格式化。

(使用Rails 3.2.8-5.0.0、Ruby 1.9.3-2.2.0、Linux进行测试)


HTML中的标记与JSON.pretty_generate一起使用,将使JSON在您的视图中看起来很漂亮。当我杰出的老板向我展示这一点时,我非常高兴:

1
2
<% if !@data.blank? %>
   [cc lang="ruby"]<%= JSON.pretty_generate(@data) %>

<%%>< /代码>


如果你想:

  • 自动美化应用程序中所有传出的JSON响应。
  • 避免污染目标
  • 避免使用中间件解析/重新呈现JSON(糟糕!)
  • 沿着铁轨走!
  • 然后…替换JSON的actionController::renderer!只需将以下代码添加到ApplicationController:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ActionController::Renderers.add :json do |json, options|
      unless json.kind_of?(String)
        json = json.as_json(options) if json.respond_to?(:as_json)
        json = JSON.pretty_generate(json, options)
      end

      if options[:callback].present?
        self.content_type ||= Mime::JS
       "#{options[:callback]}(#{json})"
      else
        self.content_type ||= Mime::JSON
        json
      end
    end

    看看很棒的印花。将JSON字符串解析为Ruby散列,然后以类似这样的出色打印方式显示:

    1
    2
    3
    4
    5
    6
    require"awesome_print"
    require"json"

    json = '{"holy": ["nested","json"],"batman!": {"a": 1,"b": 2}}'

    ap(JSON.parse(json))

    通过上面的内容,您将看到:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
     "holy" => [
        [0]"nested",
        [1]"json"
      ],
     "batman!" => {
       "a" => 1,
       "b" => 2
      }
    }

    Awesome_print还将添加一些堆栈溢出不会显示您的颜色:)


    将ActiveRecord对象转储到JSON(在Rails控制台中):

    1
    2
    3
    4
    5
    6
    7
    pp User.first.as_json

    # => {
    "id" => 1,
    "first_name" =>"Polar",
    "last_name" =>"Bear"
    }


    如果您(像我一样)发现Ruby JSON库中内置的pretty_generate选项不够"漂亮",我建议您使用我自己的NeatJSONgem进行格式化。

    使用gem install neatjson,然后使用JSON.neat_generate,而不是JSON.pretty_generate

    像Ruby的pp一样,它将对象和数组保持在一行上(如果合适),但根据需要包装成多行。例如:

    < PRE> >代码>"navigation.createroute.poi":。["text":"向希尔顿提供课程","params":"poi":"希尔顿","text":"带我去机场","params":"poi":"机场","text":"让我们转到ihop","params":"poi":"ihop","text":"演示如何到达med","params":"poi":"med","text":"创建到arby的路由","params":"poi":"arby的",{"text":"去机场旁边的希尔顿酒店","params":"poi":"希尔顿","location":"机场"}{"text":"带我去弗雷斯诺的弗莱家","params":"poi":"fry's","location":"fresno"},"navigation.eta":。["text":"我们什么时候到那里?


    使用HTML代码和pretty_generate是一个很好的技巧:

    1
    2
    3
    4
    5
    6
    7
    8
    <%
      require 'json'

      hash = JSON[{hey:"test", num: [{one: 1, two: 2, threes: [{three: 3, tthree: 33}]}]}.to_json]
    %>

    [cc lang="ruby"]
      <%=  JSON.pretty_generate(hash) %>

    < /代码>


    下面是一个中间件解决方案,它是由@gertas根据这个出色的答案进行修改的。这个解决方案不是特定于Rails的——它应该与任何机架应用程序一起工作。

    这里使用的中间件技术,每个都使用在asciicasts 151:Eifion Bedford的机架中间件中进行了解释。

    此代码位于app/middleware/pretty_json_response.rb中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    class PrettyJsonResponse

      def initialize(app)
        @app = app
      end

      def call(env)
        @status, @headers, @response = @app.call(env)
        [@status, @headers, self]
      end

      def each(&block)
        @response.each do |body|
          if @headers["Content-Type"] =~ /^application\/json/
            body = pretty_print(body)
          end
          block.call(body)
        end
      end

      private

      def pretty_print(json)
        obj = JSON.parse(json)  
        JSON.pretty_unparse(obj)
      end

    end

    要打开它,请将其添加到config/environments/test.rb和config/environments/development.rb中:

    1
    config.middleware.use"PrettyJsonResponse"

    正如@gertas在其版本的解决方案中警告的那样,避免在生产中使用它。有点慢。

    用轨道4.1.6测试。


    1
    2
    3
    4
    5
    #At Controller
    def branch
        @data = Model.all
        render json: JSON.pretty_generate(@data.as_json)
    end

    我用过gem coderay,它工作得很好。格式包括颜色,它识别出许多不同的格式。

    我在一个gem上使用了它,这个gem可以用于调试RailsAPI,并且工作得很好。

    顺便说一下,gem被命名为"api_explorer"(http://www.github.com/toptierlabs/api_explorer)


    If you're looking to quickly implement this in a Rails controller action to send a JSON response:

    1
    2
    3
    4
    def index
      my_json = '{"key":"value" }'
      render json: JSON.pretty_generate( JSON.parse my_json )
    end

    这是我自己搜索时从其他帖子中得到的解决方案。

    这允许您根据需要将pp和jj输出发送到文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    require"pp"
    require"json"

    class File
      def pp(*objs)
        objs.each {|obj|
          PP.pp(obj, self)
        }
        objs.size <= 1 ? objs.first : objs
      end
      def jj(*objs)
        objs.each {|obj|
          obj = JSON.parse(obj.to_json)
          self.puts JSON.pretty_generate(obj)
        }
        objs.size <= 1 ? objs.first : objs
      end
    end

    test_object = { :name => { first:"Christopher", last:"Mullins" }, :grades => ["English" =>"B+","Algebra" =>"A+" ] }

    test_json_object = JSON.parse(test_object.to_json)

    File.open("log/object_dump.txt","w") do |file|
      file.pp(test_object)
    end

    File.open("log/json_dump.txt","w") do |file|
      file.jj(test_json_object)
    end

    如果您使用的是rabl,那么可以按照下面的描述配置它,以使用json.pretty_generate:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class PrettyJson
      def self.dump(object)
        JSON.pretty_generate(object, {:indent =>" "})
      end
    end

    Rabl.configure do |config|
      ...
      config.json_engine = PrettyJson if Rails.env.development?
      ...
    end

    使用json.pretty_generate的一个问题是,json模式验证器将不再满足于日期时间字符串。您可以使用以下方法修复config/initializers/rabl_config.rb中的那些问题:

    1
    2
    3
    4
    5
    6
    ActiveSupport::TimeWithZone.class_eval do
      alias_method :orig_to_s, :to_s
      def to_s(format = :default)
        format == :default ? iso8601 : orig_to_s(format)
      end
    end

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    # example of use:
    a_hash = {user_info: {type:"query_service", e_mail:"my@email.com", phone:"+79876543322
    <hr><P>我使用下面的内容,因为我发现头、状态和JSON输出非常有用一套。根据Railscansts演示文稿的建议,在以下网址中列出了调用例程:http://railscansts.com/sets/151-rack-middleware?自动播放=真</P>[cc lang="
    ruby"]  class LogJson

      def initialize(app)
        @app = app
      end

      def call(env)
        dup._call(env)
      end

      def _call(env)
        @status, @headers, @response = @app.call(env)
        [@status, @headers, self]
      end

      def each(&block)
        if @headers["
    Content-Type"] =~ /^application\/json/
          obj = JSON.parse(@response.body)
          pretty_str = JSON.pretty_unparse(obj)
          @headers["
    Content-Length"] = Rack::Utils.bytesize(pretty_str).to_s
          Rails.logger.info ("
    HTTP Headers:  #{ @headers }")
          Rails.logger.info ("HTTP Status:  #{ @status }")
          Rails.logger.info ("JSON Response:  #{ pretty_str}")
        end

        @response.each(&block)
      end
      end


    推荐阅读

      linux输出结果命令?

      linux输出结果命令?,标准,工作,系统,信息,命令,文件,百度,数字,环境,设备,lin

      linux获取命令输出行?

      linux获取命令输出行?,数字,工具,系统,数据,命令,文件,内容,文本,尾部,表示,L

      linux输出字符串命令?

      linux输出字符串命令?,标准,基础,字符串,资料,简介,商业,数字,系统,命令,汉

      linux命令输出中文?

      linux命令输出中文?,系统,标的,底部,中文,命令,字符集,输入法,网络安全,级

      linux命令格式化磁盘?

      linux命令格式化磁盘?,电脑,设备,系统,管理,位置,首次,网络,数据,名称,命令,l

      linux命令输出格式化?

      linux命令输出格式化?,电脑,系统,标准,位置,设备,图片,首次,管理,网络,命令,L

      linux标准输出命令?

      linux标准输出命令?,标准,工作,系统,信息,地址,命令,环境,基础,设备,数字,lin

      漂亮的linux命令行?

      漂亮的linux命令行?,工作,系统,地址,信息,命令,目录,工具,标准,做好,基础,Lin

      linux常用输出命令?

      linux常用输出命令?,工作,系统,地址,管理,信息,标准,命令,目录,数据,位置,lin

      linux格式化登陆命令?

      linux格式化登陆命令?,电脑,设备,软件,工作,系统,地址,管理,位置,命令,名称,f

      linux声音输出命令?

      linux声音输出命令?,电脑,系统,设备,服务,软件,数据,工具,情况,手机,命令,lin

      linux命令输入格式化?

      linux命令输入格式化?,电脑,设备,系统,管理,位置,环境,名称,数据,磁盘,命令,l

      用linux命令输出id?

      用linux命令输出id?,系统,设备,工作,信息,地址,命令,工具,基础,目录,进程,lin

      linux命令输入格式化?

      linux命令输入格式化?,电脑,设备,系统,管理,位置,环境,名称,数据,磁盘,命令,l

      linux命令输出太多?

      linux命令输出太多?,命令,标准,信息,时间,名称,文件,内容,屏幕,模式,目录,lin

      linux中格式化命令行?

      linux中格式化命令行?,设备,系统,电脑,管理,位置,网络,名称,首次,磁盘,命令,l

      linux命令输出截图?

      linux命令输出截图?,工具,图片,代码,截图,环境,支柱,网络,标准,发展,命令,Lin

      linux系统输出命令?

      linux系统输出命令?,系统,工作,地址,信息,命令,工具,目录,设备,基础,发行,lin

      漂亮的linux命令教学?

      漂亮的linux命令教学?,地址,管理,命令,数据,设备,发行,单位,网络,系统,信息,l

      linux使用命令的方法?

      linux使用命令的方法?,系统,信息,工具,标准,数据,命令,左下角,目录,文件夹,