Ruby on Rails에서 JSON 출력의 형식을 "예쁘게" 지정하려면 어떻게 해야 하나요?

StackOverflow https://stackoverflow.com/questions/86653

문제

Ruby on Rails의 JSON 출력이 "예쁘거나" 형식이 좋기를 바랍니다.

지금 당장 전화해 to_json 내 JSON은 모두 한 줄에 있습니다.때때로 JSON 출력 스트림에 문제가 있는지 확인하기 어려울 수 있습니다.

내 JSON을 "예쁘게" 만들거나 Rails에서 보기 좋게 형식화하는 구성 방법이나 방법이 있습니까?

도움이 되었습니까?

해결책

사용 pretty_generate() 함수는 JSON의 이후 버전에 내장되어 있습니다.예를 들어:

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

당신은 다음을 얻을 수 있습니다 :

{
  "array": [
    1,
    2,
    3,
    {
      "sample": "hash"
    }
  ],
  "foo": "bar"
}

다른 팁

Rack Middleware 및 Rails 3 덕분에 앱 컨트롤러를 변경하지 않고도 모든 요청에 ​​대해 예쁜 JSON을 출력할 수 있습니다.나는 그러한 미들웨어 조각을 작성했으며 브라우저에 JSON이 잘 인쇄되어 있고 curl 산출.

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

위의 코드는 다음 위치에 배치되어야 합니다. app/middleware/pretty_json_response.rb Rails 프로젝트의그리고 마지막 단계는 미들웨어를 등록하는 것입니다. config/environments/development.rb:

config.middleware.use PrettyJsonResponse

나는 그것을 사용하는 것을 권장하지 않습니다 production.rb.JSON 재분석은 프로덕션 앱의 응답 시간과 처리량을 저하시킬 수 있습니다.결국 'X-Pretty-Json:요청 시 수동 컬 요청에 대한 형식 지정을 트리거하기 위해 true' 헤더가 도입될 수 있습니다.

(Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux에서 테스트됨)

그만큼 <pre> HTML의 태그, 함께 사용됨 JSON.pretty_generate, 보기에서 JSON을 보기 좋게 렌더링합니다.나의 저명한 상사가 나에게 다음을 보여주었을 때 나는 매우 기뻤습니다.

<% if @data.present? %>
   <pre><%= JSON.pretty_generate(@data) %></pre>
<% end %>

원하는 경우:

  1. 앱에서 나가는 모든 JSON 응답을 자동으로 예쁘게 만듭니다.
  2. Object#to_json/#as_json 오염 방지
  3. 미들웨어를 사용하여 JSON을 구문 분석/재렌더링하지 마세요. (으악!)
  4. RAILS WAY로 해보세요!

그 다음에 ...JSON용 ActionController::Renderer를 교체하세요!ApplicationController에 다음 코드를 추가하기만 하면 됩니다.

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

확인해 보세요 awesome_print.JSON 문자열을 Ruby Hash로 구문 분석한 후 다음과 같이 awesome_print를 사용하여 표시합니다.

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

위와 같이 보면 다음과 같습니다.

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

awesome_print는 스택 오버플로가 표시하지 않는 색상도 추가합니다 :)

ActiveRecord 객체를 JSON으로 덤프(Rails 콘솔에서):

pp User.first.as_json

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

만약 당신이 (나처럼) 그 사실을 알게 된다면 pretty_generate Ruby의 JSON 라이브러리에 내장된 옵션은 "예쁘지" 않습니다. 내 옵션을 추천합니다. NeatJSON 서식 지정을 위한 보석입니다.

그것을 사용하려면 gem install neatjson 그런 다음 사용 JSON.neat_generate 대신에 JSON.pretty_generate.

루비와 마찬가지로 pp 객체와 배열이 적합할 경우 한 줄에 유지하지만 필요에 따라 여러 줄로 줄 바꿈합니다.예를 들어:

{
  "navigation.createroute.poi":[
    {"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}},
    {"text":"Take me to the airport","params":{"poi":"airport"}},
    {"text":"Let's go to IHOP","params":{"poi":"IHOP"}},
    {"text":"Show me how to get to The Med","params":{"poi":"The Med"}},
    {"text":"Create a route to Arby's","params":{"poi":"Arby's"}},
    {
      "text":"Go to the Hilton by the Airport",
      "params":{"poi":"Hilton","location":"Airport"}
    },
    {
      "text":"Take me to the Fry's in Fresno",
      "params":{"poi":"Fry's","location":"Fresno"}
    }
  ],
  "navigation.eta":[
    {"text":"When will we get there?"},
    {"text":"When will I arrive?"},
    {"text":"What time will I get to the destination?"},
    {"text":"What time will I reach the destination?"},
    {"text":"What time will it be when I arrive?"}
  ]
}

또한 다양한 기능을 지원합니다. 서식 옵션 출력을 추가로 사용자 정의합니다.예를 들어 콜론 앞/뒤에 공백이 몇 개 있습니까?쉼표 앞/뒤?배열과 객체의 괄호 안에 있습니까?개체의 키를 정렬하시겠습니까?콜론을 모두 일렬로 정렬하시겠습니까?

사용 <pre> HTML 코드와 pretty_generate 좋은 트릭입니다:

<%
  require 'json'

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

<pre>
  <%=  JSON.pretty_generate(hash) %>
</pre>

다음은 다음에서 수정된 미들웨어 솔루션입니다. @gertas의 훌륭한 답변.이 솔루션은 Rails에만 적용되는 솔루션이 아니며 모든 Rack 애플리케이션에서 작동해야 합니다.

여기서 #each를 사용하여 사용된 미들웨어 기술은 다음에서 설명됩니다. ASCIIcast 151:랙 미들웨어 에이피온 베드포드(Eifion Bedford).

이 코드가 들어갑니다 앱/미들웨어/pretty_json_response.rb:

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에 다음을 추가하세요.

config.middleware.use "PrettyJsonResponse"

@gertas가 이 솔루션 버전에서 경고한 것처럼 프로덕션 환경에서는 사용하지 마세요.다소 느립니다.

Rails 4.1.6으로 테스트되었습니다.

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

내 검색 중에 다른 게시물에서 파생된 솔루션은 다음과 같습니다.

이를 통해 필요에 따라 pp 및 jj 출력을 파일로 보낼 수 있습니다.

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

나는 보석 CodeRay를 사용했는데 꽤 잘 작동합니다.형식에는 색상이 포함되며 다양한 형식을 인식합니다.

Rails API 디버깅에 사용할 수 있는 gem에서 이를 사용했는데 꽤 잘 작동합니다.

그런데 보석의 이름은 'api_explorer'(http://www.github.com/toptierlabs/api_explorer)

JSON 응답을 보내기 위해 Rails 컨트롤러 작업에서 이를 신속하게 구현하려는 경우:

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

헤더, 상태 및 JSON 출력이 세트로 유용한 것을 발견 할 때 다음을 사용합니다.통화 루틴은 다음 Railscasts 프레젠테이션의 권장 사항에 따라 분류됩니다. http://railscasts.com/episodes/151-rack-middleware?autoplay=true

  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

당신이 사용하는 경우 라블 설명된 대로 구성할 수 있습니다. 여기 JSON.pretty_generate를 사용하려면:

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에서 다음을 사용하여 문제를 해결할 수 있습니다.

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

# example of use:
a_hash = {user_info: {type: "query_service", e_mail: "my@email.com", phone: "+79876543322"}, cars_makers: ["bmw", "mitsubishi"], car_models: [bmw: {model: "1er", year_mfc: 2006}, mitsubishi: {model: "pajero", year_mfc: 1997}]}
pretty_html = a_hash.pretty_html

# include this module to your libs:
module MyPrettyPrint
    def pretty_html indent = 0
        result = ""
        if self.class == Hash
            self.each do |key, value|
                result += "#{key}

: #{[Array, Hash].include?(value.class) ? value.pretty_html(indent+1) : value}

" end elsif self.class == Array result = "[#{self.join(', ')}]" end "#{result}" end end class Hash include MyPrettyPrint end class Array include MyPrettyPrint end

예쁜 인쇄 변형:

my_object = { :array => [1, 2, 3, { :sample => "hash"}, 44455, 677778, 9900 ], :foo => "bar", rrr: {"pid": 63, "state": false}}
puts my_object.as_json.pretty_inspect.gsub('=>', ': ')

결과:

{"array": [1, 2, 3, {"sample": "hash"}, 44455, 677778, 9900],
 "foo": "bar",
 "rrr": {"pid": 63, "state": false}}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top