Collecting hashes into OpenStruct creates “table” entry

前端 未结 6 882
滥情空心
滥情空心 2021-02-04 05:46

Why this (evaluated in Rails console)

[{:a => :b}].collect {|x| OpenStruct.new(x)}.to_json

adds a \"table\" record in there?



        
相关标签:
6条回答
  • 2021-02-04 05:46

    With ruby 2.1.2 you can use the following to get JSON without the table root element:

    [{:a => :b}].collect {|x| OpenStruct.new(x).to_h}.to_json
     => "[{\"a\":\"b\"}]"
    
    0 讨论(0)
  • 2021-02-04 06:00

    I get around the problem by subclassing OpenStruct like so:

    class DataStruct < OpenStruct
      def as_json(*args)
        super.as_json['table']
      end
    end
    

    then you can easily convert to JSON like so:

    o = DataStruct.new(a:1, b:DataStruct.new(c:3))
    o.to_json
    # => "{\"a\":1,\"b\":{\"c\":3}}"
    

    Neat huh? So in answer to your question, you'd write this instead:

    [{:a => :b}].collect {|x| DataStruct.new(x)}.to_json
    

    giving you:

    => "[{\"a\":\"b\"}]"
    
    0 讨论(0)
  • 2021-02-04 06:01
    openstruct_array.map(&:to_h).as_json
    
    0 讨论(0)
  • 2021-02-04 06:10

    I found the other responses to be a tad confusing having landed here to just figure out how to turn my OpenStruct into a Hash or JSON. To clarify, you can just call marshal_dump on your OpenStruct.

    $ OpenStruct.new(hello: :world).to_json
    => "{\"table\":{\"hello\":\"world\"}}"
    
    $ OpenStruct.new(hello: :world).marshal_dump
    => {:hello=>:world}
    
    $ OpenStruct.new(hello: :world).marshal_dump.to_json
    => "{\"hello\":\"world\"}"
    

    I personally would be hesitant to monkey-patch OpenStruct unless you're doing it on a subclass, as it may have unintended consequences.

    0 讨论(0)
  • 2021-02-04 06:11

    Because @table is a instance variable of OpenStruct and Object#as_json returns Hash of instance variables.

    In my project, I implemented OpenStruct#as_json to override the behaviour.

    require "ostruct"
    class OpenStruct
      def as_json(options = nil)
        @table.as_json(options)
      end
    end
    
    0 讨论(0)
  • 2021-02-04 06:13

    Use marshal_dump, although this somewhat defeats the purpose of converting it to an OpenStruct beforehand:

    [{:a => :b}].collect {|x| OpenStruct.new(x).marshal_dump }.to_json
    => "[{\"a\":\"b\"}]"
    

    The shorter way would be:

    [{:a => :b}].to_json
    "[{\"a\":\"b\"}]"
    

    Alternatively you could moneky patch OpenStruct#as_json as shown in hiroshi's answer:

    require "ostruct"
    class OpenStruct
      def as_json(options = nil)
        @table.as_json(options)
      end
    end
    
    0 讨论(0)
提交回复
热议问题