在不使用任何宝石的情况下从ruby中提取JSON中的信息

时间:2014-02-16 15:05:39

标签: ruby json string hash gem

如何在不使用任何宝石的情况下从JSON格式中提取信息?字符串如下

[["B",90461],["B",85547],["B",85709],["B",85029],
["B",85487],["B",83419],["B",83411],["B",85311],["B",81335],
["B",85149],["B",85959]]

我只需要整数部分,字符串可以转换为任何类型的数据。唯一的要求是不要使用任何宝石。非常感谢。

4 个答案:

答案 0 :(得分:2)

使用Ruby的stdib JSON

require 'json'

a = '[["B",90461],["B",85547],["B",85709],["B",85029],
["B",85487],["B",83419],["B",83411],["B",85311],["B",81335],
["B",85149],["B",85959]]'

JSON.parse(a).map(&:last)
# => [90461,
#     85547,
#     85709,
#     85029,
#     85487,
#     83419,
#     83411,
#     85311,
#     81335,
#     85149,
#     85959]

另请参阅此方法:JSON::parse

答案 1 :(得分:1)

'[["B",90461],["B",85547],["B",85709],["B",85029], ["B",85487],["B",83419],["B",83411],["B",85311],["B",81335], ["B",85149],["B",85959]]'
.scan(/\d+/).map(&:to_i)
# => => [90461, 85547, 85709, 85029, 85487, 83419, 83411, 85311, 81335, 85149, 85959]

答案 2 :(得分:1)

根据这些假设进行工作:

  • 由于某种原因,你不能简单地使用Ruby的stdlib JSON库,正如其他许多人所建议的那样
  • 传入数据中的"B"字符串可能被任何其他单个有效JSON对象替换,无论多么复杂;例如{ "key1": ["ABC", { "key2": "{\"key3\": [\"DEF\"]}" }]}
  • 你只希望并确切地将数组的第二个值(总是整数)嵌套在顶层数组的一层深处;例如[[..., 123], [..., 456]]收益[123, 456]

这是你的功能:

def parse_integers_from_specific_JSON (string)
  ary_depth = 0     # Level of nesting within arrays
  obj_depth = 0     # Level of nesting within objects
  in_string = false # Flag for whether the parser is inside a string
  escaped = false   # Flag for whether the next character will be escaped
  int_buffer = ""   # String buffer for integer digits
  integers = []     # Result array of integers

  string.each_char do |c|
    if (in_string) && !(escaped) && (c == '\\')
      # When an escape character is found in a string, set the 'escaped' flag
      escaped = true
      next
    end

    if (c == '"')
      if !in_string
        # When a quote is found outside a string, enter the new string
        in_string = true

      elsif escaped
        # When an escaped quote is found within a string, ignore it

      else
        # When an unescaped quote is found within a string, exit the string
        in_string = false
      end
    end

    # If relevant, the 'escaped' flag has escaped its quote by now; unset it
    escaped = false

    if !(in_string) && (c =~ /\d/) && (obj_depth == 0) && (ary_depth == 2)
      # If a digit is encountered at the correctly nested position,
      # append it to the integer buffer string
      int_buffer << c

    elsif !(int_buffer.empty?)
      # If the integer buffer string has digits in it and the current character
      # is not a digit, flush the contents of the buffer into the result array
      integers << int_buffer.to_i
      int_buffer.clear
    end

    unless in_string
      # Check for unquoted special characters and adjust depth
      case c
      when '{' then obj_depth += 1
      when '}' then obj_depth -= 1
      when '[' then ary_depth += 1
      when ']' then ary_depth -= 1
      end
    end
  end

  return integers
end

以下是使用示例数据的增强版本显示其实际效果的片段:

incoming_data_string = (<<-JSON).strip
[
  ["B",90461],
  [[],85547],
  [["A"],85709],
  ["",85029],
  [[123,456],85487],
  [[456,[789],"A"],83419],
  [{ a: [123] },83411],
  ["B",85311],
  ["B",81335],
  ["B",85149],
  [{ "key1": ["ABC", { "key2": "{\\"key3\\": [\\"DEF\\"]}" }]},85959]
]
JSON

p parse_integers_from_specific_JSON(incoming_data_string)

#=> [90461, 85547, 85709, 85029, 85487, 83419, 83411, 85311, 81335, 85149, 85959]

这不会特别快。如果您希望速度快,请正确回答require 'json'并使用JSON::parse

答案 3 :(得分:0)

我想标准库中有一个json模块(link)。

没有解析的简单解决方案(但是使用eval,这是邪恶的):

eval('[["B",111111],["B",222222],["B",333333]]').map(&:last)