rabl icon indicating copy to clipboard operation
rabl copied to clipboard

Inconsistent JSON/XML output, missing RABL config option to collapse nodes to array consistently

Open chinshr opened this issue 11 years ago • 0 comments

The problem appears to be an inconsistency between XML and JSON output and that there is currently no config option that allows app developers to collapse nodes like {"bundles"=>[{:bundle => {...}}]} (this happens for :json response format) or {"bundles"=>"bundle"=>[{...}]} (this happens for :xml response format) to {"bundles"=>[{...}, {...}]}

The particular context is to create a generic application.rabl layout that requires this structure, e.g. {"bundles"=>[{...}, {...}], "code": "1", "message": "OK"}

# application.rabl
# Constructs a response like:
# {"bundles"=>[{...}, {...}], "code": "1", "message": "OK"}
#
object @response
node do
  case response.content_type
  when Mime::JSON
    # Since RABL converts collections to {"bundles"=>[{:bundle => {...}}]}
    # we need to apply this ugly hack to make it look such as
    # {"bundles"=>[{...}, {...}]}
    res = Yajl::Parser.parse(content_for(:layout))
    if res.try(:[], controller_name).is_a?(Array)
      res[controller_name] = res[controller_name].map {|b| b["bundle"]}
    end
    res
  when Mime::XML
    # Again RABL gives us elements like <bundles><bundle></bundle></bundles>
    # that is parsed to hash as {"bundles"=>"bundle"=>[{...}]} which
    # makes us this this hack, which transforms it to 
    # {"bundles"=>[{...}, {...}]}
    res = Nori.new(:parser => :nokogiri, :advanced_typecasting => false).parse(content_for(:layout))
    if res.try(:[], controller_name).try(:[], controller_name.singularize)
      res[controller_name] = res[controller_name][controller_name.singularize]
    end
    res
  end
end
node :code do |response|
  response.code
end
node :message do 
  response.message || [Api::Code.get_message(self.code)]
end

My index.rabl looks like this:

collection @bundles, :root => :bundles
extends "api/v2/bundles/show"

And the show.rabl like this:

object @bundle
attributes :id, :name, :status, :bundle_type, :begin_at, :end_at, :updated_at, :created_at

My config looks like this:

Rabl.configure do |config|
  config.include_json_root = true
  config.include_xml_root = false
  config.include_child_root = false
  config.xml_options = {:skip_types => true, :skip_instruct => true, :indent => 0, :dasherize => false}
end

This is related to Stack Overflow question Parsing XML to hash with RABL and Does RABL's JSON output not conform to standard? Can it?

chinshr avatar Mar 22 '13 18:03 chinshr