रूबी ऑन रूल्स में "सुंदर" प्रारूप JSON आउटपुट कैसे करें


626

मैं रूबी में रूल्स पर अपने JSON आउटपुट को "सुंदर" या अच्छी तरह से स्वरूपित करना चाहूंगा।

अभी, मैं फोन करता हूं to_jsonऔर मेरा JSON एक लाइन पर है। कई बार यह देखना मुश्किल हो जाता है कि क्या JSON आउटपुट स्ट्रीम में कोई समस्या है।

वहाँ मेरे JSON "सुंदर" या अच्छी तरह से पटरियों में स्वरूपित करने के लिए कॉन्फ़िगर करने का तरीका है?


2
सुनिश्चित नहीं हैं कि आप इसे कहाँ देख रहे हैं, लेकिन वेबकिट के कंसोल में यह किसी JSON लॉग इन या अनुरोधित एक अच्छा ट्री बनाता है।
रेयान फ्लोरेंस

8
ऐसा करते समय याद रखने वाली एक बात यह है कि अतिरिक्त व्हाट्सएप के कारण आपके JSON सामग्री का आकार गुब्बारा होगा। एक विकास के माहौल में अक्सर JSON को पढ़ना आसान होता है, लेकिन एक उत्पादन वातावरण में आप चाहते हैं कि आपकी सामग्री उतनी ही दुबली हो, जितनी कि आप इसे उपयोगकर्ता के ब्राउज़र में गति और जवाबदेही के लिए प्राप्त कर सकते हैं।
टीन मैन

2
y my_jsonयदि आप कुछ जल्दी ठीक करना चाहते हैं, तो सामान स्वरूप का उपयोग करें।
बेतरतीब

5
@randomorundefined method 'y' for main:Object
nurettin

yरेल कंसोल में उपलब्ध है।
सोफिया फेंग

जवाबों:


999

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"
}

32
निफ्टी! मैंने इसे अपने ~ / .irbrc: def json_pp (json) में डाल दिया है JSON.pretty_generate (JSON.parse (json)) को समाप्त करता है
TheDeadSerious

10
रेल में इसे उपयोगी बनाने के लिए, ऐसा लगता है कि आपको एक उत्तर देना चाहिए जिसमें कोड शामिल हो जो उसी संदर्भ में उपयोग किया जा सकता हैformat.json { render :json => @whatever }
iconoclast

9
निश्चित रूप से प्रीटिप्रिंटिंग का उपयोग केवल सर्वर-साइड डिबगिंग के लिए किया जाना चाहिए? यदि आप एक नियंत्रक में ऊपर कोड चिपकाते हैं, तो आपके पास सभी प्रतिक्रियाओं में बेकार व्हाट्सएप का टन होगा, जो कि क्लाइंट-साइड डिबगिंग के लिए भी आवश्यक नहीं है क्योंकि उनके नमक (जैसे। फायरबग) पहले से ही JSON के प्रीटिप्रिंटिंग को संभालते हैं।
लामभानसी

8
@ जपतोकल: आप अन्य बेहतर विकल्पों पर विचार कर सकते हैं, लेकिन सवाल यह था कि इसे रेल में कैसे काम किया जाए। "आप रेल में ऐसा नहीं करना चाहते" कहना एक गैर-जवाब है। जाहिर है बहुत सारे लोग इसे रेल में करना चाहते हैं।
आइकनोकॉस्ट

39
मूल पोस्टर के बारे में कुछ भी नहीं कहा है, जहां , एक रेल app में वह इस का उपयोग करना चाहता तो मैं रूबी की एक पंक्ति है कि कहीं भी काम करेंगे के साथ जवाब दिया। रेल नियंत्रक में JSON प्रतिक्रिया उत्पन्न करने के लिए इसका उपयोग करने के लिए , आपने पहले से ही अपने प्रश्न का उत्तर दिया format.json { render :json => JSON.pretty_generate(my_json) }:।
लामशाहानी

78

रैक मिडलवेयर और रेल 3 के लिए धन्यवाद, आप अपने एप्लिकेशन के किसी भी नियंत्रक को बदले बिना हर अनुरोध के लिए बहुत JSON आउटपुट कर सकते हैं। मैंने ऐसे मिडलवेयर स्निपेट लिखे हैं और मुझे ब्राउज़र और curlआउटपुट में अच्छी तरह से मुद्रित JSON मिलता है ।

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आपकी रेल परियोजना में रखा जाना चाहिए । और अंतिम चरण में मिडिलवेयर को पंजीकृत करना है config/environments/development.rb:

config.middleware.use PrettyJsonResponse

मैं इसे इस्तेमाल करने की सलाह नहीं देताproduction.rb । JSON रिपार्सिंग आपके प्रोडक्शन ऐप के रिस्पॉन्स टाइम और थ्रूपुट को नीचा दिखा सकता है। अंततः अतिरिक्त तर्क जैसे कि 'X-Pretty-Json: true' हेडर को मांग पर मैनुअल कर्ल अनुरोधों के लिए स्वरूपण को ट्रिगर करने के लिए पेश किया जा सकता है।

(रेल 3.2.8-5.0.0, रूबी 1.9.3-2.2.0, लिनक्स के साथ परीक्षण किया गया)


2
आपको ActiveSupport के to_json के पुनर्परिभाषित के आसपास कैसे मिल रहा है ? यह मुझे बहुत मुद्रण से रखता है जबकि ActiveSupport मौजूद है।
अम्मो गोएत्श

1
मुझे वास्तव में परवाह नहीं है, to_json, as_json, jbuilder, जो कि मैं ज्यादातर उपयोग करता हूं - जो भी, मिडलवेयर किसी भी SON आउटपुट को बदल देता है। मैं जब भी संभव हो कक्षा खोलने से बचने की कोशिश करता हूं।
gertas 23

1
मुझे obj = JSON.parse(response.body.first)इसे काम करने के लिए पार्स लाइन को बदलना पड़ा ।
किममो लेहटो

5
रेल 4 में महान काम करता है ... धन्यवाद! मैं इसे और अधिक लाइब्रेरी-विशिष्ट विधियों (जैसा कि स्वीकृत उत्तर में) पसंद करता हूं। चूँकि आपको केवल देव मोड में इसका उपयोग करना चाहिए, प्रदर्शन हिट कोई बड़ी बात नहीं है।
एल्सुरूडो

3
रेल 5 में मैं बदलना पड़ा Rack::Utils.bytesize(pretty_str).to_sकरने के लिए pretty_str.bytesize.to_sऔर यह बहुत अच्छा काम करता है!
पैंटो

77

<pre>टैग के ठीक बाद, के साथ प्रयोग किया JSON.pretty_generate, अपने दृश्य में सुंदर JSON प्रस्तुत करना होगा। मुझे बहुत खुशी हुई जब मेरे शानदार बॉस ने मुझे यह दिखाया:

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

5
इतना साफ और संक्षिप्त!
सीन सजको

23

यदि आप चाहते हैं:

  1. स्वचालित रूप से अपने ऐप से सभी निवर्तमान JSON प्रतिक्रियाओं को रोकें।
  2. प्रदूषणकारी वस्तु # to_json / # as_json से बचें
  3. मिडलवेयर (YUCK!) का उपयोग करके JSON को पार्स करने / पुनः प्रस्तुत करने से बचें।
  4. यह मत करो रास्ता!

तब ... ActionController की जगह :: JSON के लिए रेंडरर! बस अपने 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

यह कमाल है, लेकिन यह वास्तव में अलग-अलग तरीके से प्रस्तुत करने के लिए तारीखों / समय का कारण बनता है: gist.github.com/nornagon/9c24b68bd6d3e871add3
nornagon

इसके साथ कई समस्याएं: (1) JSON.pretty_generate की आवश्यकता है json.respond_to?(:to_h)या :to_hash। (2) pretty_generate उन चीजों पर मजाक कर सकता है जो to_json नहीं करता है।
क्रिस्टोफर ओजबेक

@nornagon मैंने इस बदलाव को लागू नहीं किया है और मुझे वही अंतर मिल रहा है जो आपने .to_json और pretty_generate के बीच देखा था। मैं इसे केवल रेल कंसोल में देखता हूं, न कि प्लेन आइआरबी में। मुझे लगता है कि यह एक सामान्य रेल की बात हो सकती है, इस पैच से कोई लेना देना नहीं है। इसके अलावा, Time.parse एक ही परिणाम देता है जब आप स्ट्रिंग को दोनों प्रारूपों के लिए समय-समय पर बदलते हैं। समय टिकटों के लिए लॉग की खोज करते समय यह केवल एक छोटी सी असुविधा होगी, लेकिन अगर आप वैसे भी कुछ \ _ + जोड़ रहे हैं तो वास्तव में एक बड़ी बात नहीं है।
con--

मुद्दा जैसी लगती है @nornagon आप देखा ActiveSupport की थी परिभाषा , to_json के रूप में उल्लेख किया बारूद Goettsch की टिप्पणी
con--

17

की जाँच करें बहुत बढ़िया प्रिंट । रूबी हैश में JSON स्ट्रिंग को पार्स करें, फिर इसे इस apतरह प्रदर्शित करें:

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
  }
}

बहुत बढ़िया प्रिंट कुछ रंग भी जोड़ देगा जो स्टैक ओवरफ्लो आपको नहीं दिखाएंगे।


2
आप से सहमत! भयानक_प्रिंट सरल भयानक है!
आशीष

2
हम अपनी परियोजनाओं के लिए भी भयानक_प्रिंट का उपयोग कर रहे हैं और यह नाम की तरह काम करता है -> कमाल
साइमन फ्रेंज़ेन

13

JSON (रेल कंसोल में एक ActiveRecord ऑब्जेक्ट डंपिंग):

pp User.first.as_json

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

3
ppमानक आउटपुट पर मुद्रण के बजाय स्ट्रिंग प्राप्त करने के लिए, उपयोग करें User.first.as_json.pretty_inspect। मेरे लिए अच्छा काम करता है।
जॉनी वोंग

12

<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>

12

यदि आप पाते हैं कि pretty_generateरूबी के 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?"}
  ]
}

यह आपके आउटपुट को और अधिक अनुकूलित करने के लिए विभिन्न प्रकार के स्वरूपण विकल्पों का भी समर्थन करता है । उदाहरण के लिए, कॉलोन से पहले / बाद में कितने स्थान? अल्पविराम से पहले / बाद में सरणियों और वस्तुओं के कोष्ठक के अंदर? क्या आप अपनी वस्तु की चाबी छांटना चाहते हैं? क्या आप चाहते हैं कि सभी के लिए कॉलोन को लाइन में खड़ा किया जाए?


2
यह रत्न चट्टानों - कॉलोन पर संरेखित विशेष रूप से मीठा है!
webdevguy

8

यहाँ @gertas द्वारा इस उत्कृष्ट उत्तर से संशोधित एक मिडलवेयर समाधान है । यह समाधान रेल विशिष्ट नहीं है - यह किसी भी रैक अनुप्रयोग के साथ काम करना चाहिए।

यहाँ पर इस्तेमाल की जाने वाली मिडिलवेयर तकनीक # एच का उपयोग करते हुए ASCIIcasts 151: रैक मिडलवेयर को इफियन बेडफोर्ड द्वारा समझाया गया है।

यह कोड ऐप / मिडलवेयर / 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

इसे चालू करने के लिए, इसे कॉन्फ़िगर / वातावरण / test.rb और config / environment / development.rb में जोड़ें:

config.middleware.use "PrettyJsonResponse"

जैसा कि @gertas इस समाधान के अपने संस्करण में चेतावनी देता है, उत्पादन में इसका उपयोग करने से बचें। यह कुछ धीमा है।

4.1.6 रेल के साथ परीक्षण किया गया।



4

यहाँ मेरा समाधान है जो मैंने अपनी खोज के दौरान अन्य पदों से लिया है।

यह आपको जरूरत के अनुसार पीपी और जेजी आउटपुट को फाइल में भेजने की अनुमति देता है।

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

3

मैं मणि CodeRay का उपयोग किया है और यह बहुत अच्छी तरह से काम करता है। प्रारूप में रंग शामिल हैं और यह बहुत सारे विभिन्न स्वरूपों को पहचानता है।

मैंने इसका उपयोग एक ऐसे मणि पर किया है जिसका उपयोग एपीआई की रेलिंग डिबगिंग के लिए किया जा सकता है और यह बहुत अच्छी तरह से काम करता है।

वैसे, मणि का नाम 'api_explorer' ( http://www.github.com/toptierlabs/api_explorer ) है


3

यदि आप JSON प्रतिक्रिया भेजने के लिए रेल कंट्रोलर एक्शन में इसे जल्दी लागू करना चाहते हैं:

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

2

यदि आप RABL का उपयोग कर रहे हैं, तो आप इसे 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 स्कीमा सत्यापनकर्ता अब आपके डेटाटाइम स्ट्रिंग्स से खुश नहीं होंगे। आप अपने कॉन्‍फ़िगरेशन / इनिशियलाइज़र / 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

2

# 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

1

मैं निम्नलिखित का उपयोग करता हूं क्योंकि मुझे हेडर, स्थिति और JSON आउटपुट एक सेट के रूप में उपयोगी लगते हैं। कॉल रूटीन प्रस्तुति पर सिफारिश से टूट गया है: 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

1

सुंदर प्रिंट संस्करण:

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}}

0

सबसे सरल उदाहरण, मैं सोच सकता था:

my_json = '{ "name":"John", "age":30, "car":null }'
puts JSON.pretty_generate(JSON.parse(my_json))

रेल कंसोल का उदाहरण:

core dev 1555:0> my_json = '{ "name":"John", "age":30, "car":null }'
=> "{ \"name\":\"John\", \"age\":30, \"car\":null }"
core dev 1556:0> puts JSON.pretty_generate(JSON.parse(my_json))
{
  "name": "John",
  "age": 30,
  "car": null
}
=> nil
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.