Поиск ответа JSON с использованием Ruby

Я использую сценарий Ruby для взаимодействия с API приложения, и возвращаемые результаты имеют формат JSON. Например:

{
  "incidents": [
    {
      "number": 1,
      "status": "open",
      "key": "abc123"
    }
    {
      "number": 2,
      "status": "open",
      "key": "xyz098"
    }
    {
      "number": 3,
      "status": "closed",
      "key": "lmn456"
    }
  ]
}

Я ищу в каждом блоке определенное значение «ключа» (yzx098 в этом примере) и возвращаю связанное значение «число».

Теперь я очень новичок в Ruby, и я не уверен, что уже есть функция, которая поможет это сделать. Однако пара дней поиска в справочниках Google и Ruby не дала ничего работающего.

Какие-либо предложения?


person Kristopher    schedule 14.03.2014    source источник
comment
Вы ищете модуль JSON для стандартная библиотека?   -  person matt    schedule 15.03.2014
comment
Хэши нуждаются в запятых между ними, чтобы быть допустимыми для разбора json. Я пытался отредактировать Q, но нужно изменить 6 символов - нельзя добавить 2 запятые :)   -  person Mike Vormwald    schedule 15.03.2014


Ответы (2)


Прежде всего, JSON должен быть следующим: (обратите внимание на запятые)

 {
  "incidents": [
    {
      "number": 1,
      "status": "open",
      "key": "abc123"
    },
    {
      "number": 2,
      "status": "open",
      "key": "xyz098"
    },
    {
      "number": 3,
      "status": "closed",
      "key": "lmn456"
    }
  ]
}

Сохраните вышеуказанный json в переменной

s =  '{"incidents": [{"number": 1,"status": "open","key": "abc123"},{"number": 2,"status": "open","key": "xyz098"},{"number": 3,"status": "closed","key": "lmn456"}]}'

Разобрать JSON

h = JSON.parse(s)

Найдите нужный number с помощью map

h["incidents"].map {|h1| h1['number'] if h1['key']=='xyz098'}.compact.first

Или вы также можете использовать find, как показано ниже.

 h["incidents"].find {|h1| h1['key']=='xyz098'}['number']

Или вы также можете использовать select, как показано ниже.

h["incidents"].select {|h1| h1['key']=='xyz098'}.first['number']
person Kirti Thorat    schedule 14.03.2014
comment
не нужно if.... select или find отбрасывает выбор всякий раз, когда блок возвращает true. Достаточно только h1['key']=='xyz098'. - person Arup Rakshit; 15.03.2014
comment
Спасибо за помощь! Направил меня в правильном направлении, и я смог разобраться с этим. Ваше здоровье! - person Kristopher; 18.03.2014

Сделайте, как показано ниже

# to get numbers from `'key'`.
json_hash["incidents"].map { |h| h['key'][/\d+/].to_i }
  • json_hash["incidents"] - даст вам значение ключа "incidents", который представляет собой не что иное, как массив хэшей.

  • map для тщательного повторения каждого хэша и собрать значение 'key'. Затем применяя Hash#[] к каждому внутренний хэш массива, чтобы получить значение "key". Затем вызовите str[regexp], чтобы получить только числовые строки, такие как '098' из "xyz098", наконец, применив to_i, чтобы получить из него фактическое целое число.

Если данный хеш на самом деле представляет собой строку json, то сначала проанализируйте ее, используя JSON::parse, чтобы преобразовать его в хеш. Затем выполните итерацию, как я сказал выше.

require 'json'

json_hash = JSON.parse(json_string)
# to get values from the key `"number"`.
json_hash["incidents"].map { |h| h['number'] } # => [1, 2, 3]
# to search and get all the numbers for a particular key match and take the first
json_hash["incidents"].select { |h| h['key'] == 'abc123' }.first['number'] # => 1
# or to search and get only the first number for a particular key match
json_hash["incidents"].find { |h| h['key'] == 'abc123' }['number'] # => 1
person Arup Rakshit    schedule 14.03.2014
comment
Я полагаю, что он запрашивал поле "number" хэша с ключом "xyz098" Это можно сделать с помощью чего-то вроде json_hash["incidents"].select { |h| h['key'] == 'abc123' }.first['number'], что дает вам 2 - person Mike Vormwald; 15.03.2014