Получить дочерние элементы JSON одного узла со случайным именем в Groovy

В Groovy (не Grails) я хочу получить цвет такого элемента:

{
    "8436": {
        "color": "red",
    }
}

Номер "8436" динамический, но всегда только один.

Я не могу использовать синтаксис JsonSlurper json.8436.color, потому что число будет жестко запрограммировано.

Как получить цвет?


person Nicolas Raoul    schedule 28.09.2016    source источник


Ответы (3)


Другой вариант, учитывая:

def jsonStr = '''{
    "8436": {
        "color": "red",
    }
}'''

Вы можете сделать:

import groovy.json.JsonSlurper

def json = new JsonSlurper().parseText(jsonStr)

def (rootKey, color) = json.findResult { k, v -> [k, v.color] }

assert rootKey == '8436'
assert color == 'red'
person tim_yates    schedule 28.09.2016

Поскольку вы немного знаете о структуре вашего ввода json, вы можете воспользоваться тем фактом, что корень — это карта, содержащая один ключ.

Как это:

import groovy.json.JsonSlurper
def json = new JsonSlurper().parseText('{"8436":{"color":"red"}}')
def rootKey = json.keySet()[0]
assert rootKey == '8436'
assert json[rootKey].color == 'red'
person Steinar    schedule 28.09.2016
comment
Получение rootKey — действительно отличный первый шаг! К сожалению, когда я помещаю ваш код в файл и запускаю его, я получаю No signature of method: java.util.HashMap$KeySet.getAt() is applicable for argument types: (java.lang.Integer) values: [0] - person Nicolas Raoul; 28.09.2016
comment
На ум приходит несколько решений этой ошибки: (1) выбрать первый элемент из итератора набора: json.keySet().iterator().next(), (2) привести набор к списку и индексу, как и раньше: (json.keySet() as List)[0], (3) начать с пустого списка и добавьте к нему набор, затем проиндексируйте, как и раньше: `([] + json.keySet())[0] и так далее, со многими вариациями на тему. - person BalRog; 28.09.2016
comment
Кстати, Iterable.getAt(int) определен в Groovy, поэтому я не могу понять, почему java.util.HashMap$KeySet его не распознает, поскольку этот класс реализует Iterable (посредством Collection, путем Set). Мне кажется, это ошибка в Groovy, но раньше я ошибался. - person BalRog; 28.09.2016
comment
@NicolasRaoul Я запустил код в консоли Groovy до того, как он был отправлен, возможно, мы используем разные версии Groovy (у меня 2.4.7)? Не уверен, когда getAt() был добавлен в Iterator. Однако предложение БалРога: keySet().iterator().next() должно работать в любой заводной версии. - person Steinar; 29.09.2016
comment
Я использую Groovy Ubuntu 2016.04, который на удивление устарел: 1.8.6. - person Nicolas Raoul; 29.09.2016

Обновление: лучший (более идиоматический?) способ

import groovy.json.JsonSlurper

def jsonStr = """
{
    "8436": {
        "color": "red",
    }
}
"""
def json = new JsonSlurper().parseText(jsonStr)

def color = json.each {}.collect{it.value.color}[0]

println color

======= старая версия, хранящаяся во внешней переменной закрытия =======

Почему бы не что-то вроде этого:

import groovy.json.JsonSlurper

def jsonStr = """
{
    "8436": {
        "color": "red",
    }
}
"""
def json = new JsonSlurper().parseText(jsonStr)

def color
json.each { color = it.value.color}

println color
person KoW    schedule 28.09.2016
comment
Мне никогда не нравится изменять значения вне замыкания внутри замыкания: -/ - person tim_yates; 28.09.2016