2

In Groovy (not Grails), I want to get the color of such an item:

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

The "8436" number is dynamic, but there is always only one.

I can't use JsonSlurper's json.8436.color syntax, because the number would be hard-coded.

How to get the color?

Nicolas Raoul
  • 58,567
  • 58
  • 222
  • 373

3 Answers3

4

Another option, given:

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

You could do:

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'
tim_yates
  • 167,322
  • 27
  • 342
  • 338
2

Since you know a bit about the structure of your json input, you can take advantage of the fact that the root is a map that contains one key.

Like this:

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'
Steinar
  • 5,860
  • 1
  • 25
  • 23
  • Getting the rootKey is a great first step indeed! Unfortunately when I put your code in a file and run it I get `No signature of method: java.util.HashMap$KeySet.getAt() is applicable for argument types: (java.lang.Integer) values: [0]` – Nicolas Raoul Sep 28 '16 at 13:48
  • Several solutions to this error to this pop to mind: (1) pick the first item off of the set's iterator: `json.keySet().iterator().next()`, (2) coerce the set to a list and index as before: `(json.keySet() as List)[0]`, (3) start with an empty list and add the set to it then index as before: `([] + json.keySet())[0], and so on, with many variations on the theme. – BalRog Sep 28 '16 at 16:45
  • BTW, `Iterable.getAt(int)` is defined in Groovy, so I can't imagine why `java.util.HashMap$KeySet` does not recognize it, since that class implements `Iterable` (by way of `Collection`, by way of `Set`). This would seem to me to be a bug in Groovy, but I have been wrong about that before. – BalRog Sep 28 '16 at 16:49
  • @NicolasRaoul I ran the code in groovy console before it was submitted, perhaps we're using different groovy versions (I'm on 2.4.7)? Not sure when `getAt()` was added on Iterator. However, BalRog's suggestion: `keySet().iterator().next()` should work in any groovy version. – Steinar Sep 28 '16 at 21:22
  • I am using Ubuntu 2016.04's Groovy, which is surprisingly old: 1.8.6 – Nicolas Raoul Sep 29 '16 at 02:49
0

Update: better (more idiomatic?) way

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

======= old version, storing in an closure-external variable =======

Why not something like this:

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
KoW
  • 784
  • 5
  • 12