【问题标题】:How to create a JSON structure in Ruby manually?如何在 Ruby 中手动创建 JSON 结构?
【发布时间】:2016-07-25 21:18:56
【问题描述】:

我花了最后几个小时尝试手动(没有 Active Record 来创建这样的结构,取自 API 的文档:

params_map = '{ "field1" => {"field1a"=>"some text"},
                "field2" => {
                  "field2a"  => "a",
                  "field2b"  => "b",
                  "field2c"  => "c",
                  "field2d"  => {"field2d_a" => "2d_a"},
                  "field2e"  => "e",
                  "items"    => [
                    { "items_a" => "1", 
                      "items_b" => "2",
                      "items_c" => "3",
                      "items_d" => "4"
                    },
                    { "items_e" => "5", 
                      "items_f" => "6",
                      "items_g" => "7",
                      "items_h" => "8"
                    }]
                },
                "field3" => "field3 text",
                "field4" => "field4 text"}'
params_map_eval = eval(params_map)

如何在 Ruby 中创建它?我尝试使用Hash.new 将其创建为哈希,也将其创建为 JSON,但我未能将其他字段添加/附加到大 JSON。

items 将是一个循环,我将从数据库中填充它,但是如何在 Ruby 中创建这个结构?

【问题讨论】:

  • 我不确定是否有更新 JSON 的好方法。是否可以将其用作哈希,然后在完成处理后将其转换为 JSON?
  • 是的,这应该不是问题,因为最终结构将如上所示。我通过哈希尝试了它,但我在连接哈希项时失败了。
  • 您可以使用Hash#merge 和#merge!。我认为#merge! 更快并且使用更少的内存,因为它不需要复制数据。见ruby-doc.org/core-2.2.0/Hash.html#method-i-merge
  • 您的 params_map 不是 JSON,它是哈希哈希的字符串版本。取下包装 ',您可以将其分配给 params_map 并获得一个 Ruby 哈希哈希。很难理解你的问题。
  • 我同意@theTinMan。如果您有 JSON 字符串,请使用 JSON#parse 将其转换为 Hash,然后按照您喜欢的方式继续操作。

标签: ruby-on-rails ruby json hash


【解决方案1】:

到目前为止,最简单的方法是简单地创建一个与 JSON 结构相似的散列,然后简单地在该散列上调用 .to_json。 您无需执行任何容易出错/有 XSS 风险的字符串连接来手动创建 JSON。

您可以使用所有 Ruby 语言来生成哈希,包括循环、映射、变量、合并哈希、字符串插值等。

一旦哈希与 JSON 具有相同的结构,然后只需调用 .to_json 即可,瞧,您就有了有效的 JSON 编码版本的哈希。

只要您在哈希中使用的数据类型是有效的 JSON“原始”,即 nil、字符串、数字、数组和其他哈希,并且所有哈希键都是字符串(或符号)或数字,这应该创建一个 Ruby 哈希到 JSON 哈希的 1:1 映射。

要生成原始帖子中给出的上述示例,您可以像这样构建哈希:

params_map = {}
params_map[:field1] = { :field1a => 'some_text' } 
params_map[:field2] = { :field2a =>  'a', :field2b => 'b', :field2c =>  'c' }
params_map[:field2][:field2d] = { :field2d_a => '2d_a' }
params_map[:field2][:field2e] = :e

items = 
[{  :items_a => "1",
    :items_b => "2",
    :items_c => "3",
    :items_d => "4"
}]
items.push({
    :items_e => '5',
    :items_f => '6',
    :items_g => '7'
}.merge('item_h' => "8"))

params_map[:field2][:items] = items
params_map[:field3] = "Field3 text"
params_map.merge!(:field4 => "field4_text")

注意我是如何使用不同的 Ruby 特性来构建散列的。

如果你检查最后的哈希,它看起来像这样

>> params_map
=> {:field1=>{:field1a=>"some_text"}, :field2=>{:field2a=>"a", :field2b=>"b", :field2c=>"c", :field2d=>{:field2d_a=>"2d_a"}, :field2e=>:e, :items=>[{:items_a=>"1", :items_b=>"2", :items_c=>"3", :items_d=>"4"}]}, :field3=>"Field3 text"}

然后,您可以简单地在散列上调用 params_map.to_json、JSON.dump(params_map) 或 JSON.pretty_generate(params_map) 以获取散列的 JSON 表示,这实际上是有效的 JSON。

 >> json = JSON.pretty_generate(params_map) #or use params_map.to_json or JSON.dump(params_map)
 >> puts json
{
  "field1": {
    "field1a": "some_text"
  },
  "field2": {
    "field2a": "a",
    "field2b": "b",
    "field2c": "c",
    "field2d": {
      "field2d_a": "2d_a"
    },
    "field2e": "e",
    "items": [
      {
        "items_a": "1",
        "items_b": "2",
        "items_c": "3",
        "items_d": "4"
      },
      {
        "items_e": "5",
        "items_f": "6",
        "items_g": "7",
        "item_h": "8"
      }
    ]
  },
  "field3": "Field3 text",
  "field4": "field4_text"
}

然后,要对 JSON 进行任何更改,只需使用 Ruby 编辑原始的 params_map 哈希并再次调用 .to_json / JSON.dump / JSON.pretty_generate

【讨论】:

    【解决方案2】:

    如果您想创建 JSON,请使用 Ruby 附带的 JSON 标准库:

    require 'json'
    
    foo = {
      'a' => 1,
      'b' => [2,3]
    }
    
    puts JSON[foo]
    # >> {"a":1,"b":[2,3]}
    

    如果您想弄清楚如何基于 Ruby 哈希或数组创建特定的 JSON 输出,可以通过反转过程并从所需 JSON 的样本开始,然后让解析器将其转换为基础对象:

    JSON['{"a":1,"b":[2,3]}'] # => {"a"=>1, "b"=>[2, 3]}
    

    要修改现有的 JSON 字符串,请将其解析为 Ruby 对象,修改它,然后再次输出:

    bar = JSON['{"a":1,"b":[2,3]}']
    bar['c'] = 'more data'
    
    puts JSON[bar]
    
    # >> {"a":1,"b":[2,3],"c":"more data"}
    

    请务必注意您的示例

    params_map = '{ "field1" => {"field1a"=>"some text"},
                    "field2" => {
                      "field2a"  => "a",
                      "field2b"  => "b",
                      "field2c"  => "c",
                      "field2d"  => {"field2d_a" => "2d_a"},
                      "field2e"  => "e",
                      "items"    => [
                        { "items_a" => "1", 
                          "items_b" => "2",
                          "items_c" => "3",
                          "items_d" => "4"
                        },
                        { "items_e" => "5", 
                          "items_f" => "6",
                          "items_g" => "7",
                          "items_h" => "8"
                        }]
                    },
                    "field3" => "field3 text",
                    "field4" => "field4 text"}'
    

    不是 JSON。这是一个字符串:

    foo = '{"a" => 1}'
    foo.class  # => String
    

    去掉包装',你就有了一个散列:

    foo = {"a" => 1, "b" => {"c" => 3}}
    foo.class  # => Hash
    

    【讨论】:

    • 谢谢@theTinMan,但是在发布后如何将另一个项目添加到foo?
    • 查看答案的最终版本。
    【解决方案3】:

    合并或更新 Ruby 哈希

    一般情况下,正确的做法是使用Hash#merge! 或Hash#update 修改一个Ruby 哈希的内容,然后将结果转换为JSON。例如:

    require 'json'
    
    # Add items to your Hash object.    
    params_map = {'field1' => 'foo', 'field2' => 'bar', 'field3' => 'baz'}
    params_map.merge! 'field4' => 'quux'
    #=> {"field1"=>"foo", "field2"=>"bar", "field3"=>"baz", "field4"=>"quux"}
    
    # Convert Hash object to JSON string.
    params_map.to_json
    #=> "{\"field1\":\"foo\",\"field2\":\"bar\",\"field3\":\"baz\",\"field4\":\"quux\"}"
    

    【讨论】:

      【解决方案4】:

      您可以尝试使用 OpenStruct http://ruby-doc.org/stdlib-2.0.0/libdoc/ostruct/rdoc/OpenStruct.html,您可以迭代您的数据库并即时添加新的密钥对。

      简单示例:

      struct = OpenStruct.new
      struct.foo = 'bar'
      struct.baz = 'biz'
      json_struct = struct.to_json
      
      --> {"foo": "bar", "baz": "biz"}
      

      【讨论】:

        【解决方案5】:

        Ruby 有一个可用于处理 JSON 文件的库。在 StackOverflow 中做一个简单的搜索,我得到了这个老问题。

        How to write to a JSON file in the correct format

        祝你好运!

        【讨论】:

          猜你喜欢
          • 2010-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-24
          • 2023-04-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多