【问题标题】:Ruby to convert nested array field to nested JSON objectsRuby 将嵌套数组字段转换为嵌套 JSON 对象
【发布时间】:2019-03-28 15:28:53
【问题描述】:

我正在使用 ELK Stack Logstash,这是我现在需要转换的“目标”数据字段的格式:

{
    "target": [
        "Sector1 - Subsector1",
        "Sector2 - Subsector2"
    ]
}

我需要的 JSON 输出格式:

{
    "target": [{
        "Sector": "Sector1",
        "Subsector": "Subsector1"
    }, {
        "Sector": "Sector2",
        "Subsector": "Subsector2"
    }]
}

我做了一些研究,发现 Logstash Ruby 过滤器能够执行转换,但是我不精通 Ruby,所以如果这里有任何专业人士可以帮助处理代码,将不胜感激!

【问题讨论】:

  • 如果上面是ruby hash 'h',所有内容都是字符串,你可以得到所需的格式,h['target'] = [h['target'].inject({}) { |m, i| m[i.split(' - ')[0]] = i.split(' - ')[1]; m }]
  • @ray:如果上面是 Ruby 哈希,那么您的代码将无法工作 - 您需要 h[:target],而不是 h['target']。 :)
  • @Amadan 我在评论中提到将所有内容都放在字符串中,因为如果目标是符号,则不能像 'target': 那样写,必须使用 target:。我使用'target' => 为字符串提供了解决方案

标签: arrays json ruby nested logstash


【解决方案1】:

假设输入是 JSON:

require 'json'

json = <<-EOF
{
    "target": [
        "Sector1 - Subsector1",
        "Sector2 - Subsector2"
    ]
}
EOF


data = JSON.parse(json)
data['target'].map! { |line|
  line.split(' - ').map { |str| [str[/^.*(?=\d+$)/], str] }.to_h
}
json = JSON.dump(data)

map! 将就地替换target;对于每个元素,用破折号分隔,通过省略部分末尾的数字从每个部分中提取键,并从 [key, part] 对的集合中生成哈希。

编辑:如果输入不是 JSON,而是 Ruby Hash(已经在 data 变量中),则将 data["target"] 更改为 data[:target]

【讨论】:

  • 您确定这适用于输入数据吗?我认为您是倒退的,您的输入数据是 OP 所需的输出。
  • @lacostenycoder:如果您自然地假设两个并行结构都是 JSON,那么它适用于输入数据,因为 OP 明确表示第二个是 JSON。我看到你和 ray 假设第一个是 Ruby(即使没有任何提示)。你们俩(编辑:现在也是 iGian)还假设输入中只会有一个破折号,我没有(但公平地说,这就是在 OP 的示例中可见的所有内容,再次,没有任何提示或其他)。
  • 很公平,但是在您的回答中,也许您可​​以举例说明您的输入数据需要如何定义为带有.json 的红宝石。考虑到 OP 是一个红宝石菜鸟,一些解释不会受到伤害。
【解决方案2】:

这种方法采用您的示例输入数据并将其定义为 ruby​​ 哈希,然后修改数据,然后将其格式化回 json。此外,我在这里使用的样式旨在让 ruby​​ 新手更具可读性。

require 'json'

data = {
    "target": [
        "Sector1 - Subsector1",
        "Sector2 - Subsector2"
    ]
}

data[:target] = [
  data[:target].inject({}) do |str, index|
    str[index.split(' - ')[0]] = index.split(' - ')[1]
    str
  end
]

json = data.to_json
puts json
#=>{"target":[{"Sector1":"Subsector1","Sector2":"Subsector2"}]}

【讨论】:

    【解决方案3】:

    其他选项:

    require 'json'
    
    data.transform_values { |v| v.map { |e| {Sector: e.split(" - ").first, Subsector: e.split(" - ").last } } }.to_json
    
    #=> {"target":[{"Sector":"Sector1","Subsector":"Subsector1"},{"Sector":"Sector2","Subsector":"Subsector2"}]}
    

    【讨论】:

    • 我必须使用具有自己语法格式的 Logstash Ruby 过滤器插件:elastic.co/guide/en/logstash/current/plugins-filters-ruby.html。你的答案看起来很有希望,你有机会修改你的答案以适应这个插件的语法吗?
    • 我根本不知道logstash。这只是我的猜测:也许您可以将哈希传递给 fiter 并将 json 作为输出?在这种情况下,只需尝试删除 .to_json 并传递生成的哈希值。不需要require 'json'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    • 2019-01-31
    相关资源
    最近更新 更多