首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何以编程方式识别JSON文档中哪些键具有子键-值对?

如何以编程方式识别JSON文档中哪些键具有子键-值对?
EN

Stack Overflow用户
提问于 2015-01-06 16:33:52
回答 3查看 374关注 0票数 0

我获取一个JSON文档,并需要以编程的方式“夷平”另一个第三方服务的键。

这意味着,如果我的JSON文档返回如下内容:

代码语言:javascript
复制
{'first_name' => "Joe", 'hoffman' => {'patterns' => ['negativity', 'self-sabotage'], 'right_road' => 'happy family'}, 'mbti' => 'INTJ'}

我需要知道如何为这样的第三方服务创建一个“平面”键值对:

代码语言:javascript
复制
first_name = "Joe"
hoffman.patterns = "negativity, self-sabotage"
hoffman.right_road = "happy family"
mbti = "INTJ"

一旦我知道有一个子文档,我想我已经找到了在子键中附加key + '.' + "{subkey}"的解析,但是现在,我不知道哪些是直接的键值,哪些是子文档。

问题:

我如何解析JSON来知道哪些键有子文档(额外的键值)?

( b)关于如何从数组创建字符串的建议

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-06 16:50:15

您还可以通过猴子补丁Hash来实现这一点,如下所示:

代码语言:javascript
复制
class Hash
  def flatten_keys(prefix=nil)
    each_pair.map do |k,v|
      key = [prefix,k].compact.join(".")
      v.is_a?(Hash) ? v.flatten_keys(key) : [key,v.is_a?(Array) ? v.join(", ") : v]
    end.flatten.each_slice(2).to_a
  end
  def to_flat_hash
    Hash[flatten_keys]
  end
end

那就会是

代码语言:javascript
复制
require 'json'
h = JSON.parse(YOUR_JSON_RESPONSE)
#=> {'first_name' => "Joe", 'hoffman' => {'patterns' => ['negativity', 'self-sabotage'], 'right_road' => 'happy family'}, 'mbti' => 'INTJ'}
h.to_flat_hash
#=> {"first_name"=>"Joe", "hoffman.patterns"=>"negativity, self-sabotage", "hoffman.right_road"=>"happy family", "mbti"=>"INTJ"}

也将与其他嵌套一起工作。

代码语言:javascript
复制
h =  {"first_name"=>"Joe", "hoffman"=>{"patterns"=>["negativity", "self-sabotage"], "right_road"=>"happy family", "wrong_road"=>{"bad_choices"=>["alcohol", "heroin"]}}, "mbti"=>"INTJ"}
h.to_flat_hash
#=> {"first_name"=>"Joe", "hoffman.patterns"=>"negativity, self-sabotage", "hoffman.right_road"=>"happy family", "hoffman.wrong_road.bad_choices"=>"alcohol, heroin", "mbti"=>"INTJ"}
票数 1
EN

Stack Overflow用户

发布于 2015-01-06 16:58:16

快速和肮脏的递归过程:

代码语言:javascript
复制
# assuming you've already `JSON.parse` the incoming json into this hash:
a = {'first_name' => "Joe", 'hoffman' => {'patterns' => ['negativity', 'self-sabotage'], 'right_road' => 'happy family'}, 'mbti' => 'INTJ'}

# define a recursive proc:
flatten_keys = -> (h, prefix = "") do
  @flattened_keys ||= {}
  h.each do |key, value|
    # Here we check if there's "sub documents" by asking if the value is a Hash
    # we also pass in the name of the current prefix and key and append a . to it
    if value.is_a? Hash
      flatten_keys.call value, "#{prefix}#{key}."
    else
      # if not we concatenate the key and the prefix and add it to the @flattened_keys hash 
      @flattened_keys["#{prefix}#{key}"] = value
    end
  end
  @flattened_keys
end

flattened = flatten_keys.call a
# => "first_name"=>"Joe", "hoffman.patterns"=>["negativity", "self-sabotage"], "hoffman.right_road"=>"happy family", "mbti"=>"INTJ"}

然后,要将数组转换为字符串,只需将其转换为join

代码语言:javascript
复制
flattened.inject({}) do |hash, (key, value)|
  value = value.join(', ') if value.is_a? Array
  hash.merge! key => value
end

# => {"first_name"=>"Joe", "hoffman.patterns"=>"negativity, self-sabotage", "hoffman.right_road"=>"happy family", "mbti"=>"INTJ"}
票数 0
EN

Stack Overflow用户

发布于 2015-01-06 17:32:26

另一种方式,受this post的启发

代码语言:javascript
复制
def flat_hash(h,f=[],g={})
  return g.update({ f=>h }) unless h.is_a? Hash
  h.each { |k,r| flat_hash(r,f+[k],g) }
  g
end

h = { :a => { :b => { :c => 1,
                      :d => 2 },
              :e => 3 },
      :f => 4 }

result = {}
flat_hash(h) #=> {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}
  .each{ |k, v| result[k.join('.')] = v } #=> {"a.b.c"=>1, "a.b.d"=>2, "a.e"=>3, "f"=>4}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27803012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档