5

I have a path for an object within an object within an object and I want to set it using Groovy's dynamic abilities. Usually you can do so just by doing the following:

class Foo {
  String bar
}


Foo foo = new Foo
foo."bar" = 'foobar'

That works OK. But what if you have nested objects? Something like:

class Foo {
  Bar bar
}

class Bar {
  String setMe
}

Now I want to use the dynamic setting, but

Foo foo = new Foo()
foo."bar.setMe" = 'This is the string I set into Bar'

Returns a MissingFieldException.

Any hints?

UPDATE: Thanks to Tim for pointing me in the right direction, the initial code on there works great at retrieving a property, but I need to set the value using the path string.

Here's what I came up with from the page Tim suggested:

  def getProperty(object, String propertyPath) {
    propertyPath.tokenize('.').inject object, {obj, prop ->
      obj[prop]
    }
  }

  void setProperty(Object object, String propertyPath, Object value) {
    def pathElements = propertyPath.tokenize('.')
    Object parent = getProperty(object, pathElements[0..-2].join('.'))
    parent[pathElements[-1]] = value
  }
Jim Gough
  • 148
  • 3
  • 12
  • 1
    http://stackoverflow.com/questions/5488689/how-to-retrieve-nested-properties-in-groovy – tim_yates Mar 19 '13 at 18:26
  • I was able to accomplish the task by building upon and using the getProperty method, I'll put the answer above since the comment section isn't very good to place code into – Jim Gough Mar 19 '13 at 22:18

1 Answers1

1

Following works correctly.

foo."bar"."setMe" = 'This is the string I set into Bar';

Without getProperty overriding you can achieve the same result using "${}" syntax for GString as the below code demonstrates

class Baz {
    String something
}

class Bar {

    Baz baz

}

class Foo {
    Bar bar
}

def foo = new Foo()
foo.bar = new Bar()
foo.bar.baz = new Baz()

def target = foo
def path = ["bar", "baz"]
for (value in path) {
    target = target."${value}"
}

target."something" = "someValue"
println foo.bar.baz.something

final println prints "someValue" as expected

Dev Blanked
  • 8,555
  • 3
  • 26
  • 32
  • 1
    Just a small addition to this excellent answer for others to avoid stumbling on this: You'll need to explicitly use `double quotes` for this to work, as GStrings(with expressions inside) are defined that way. But I guess all you groovy programmers already knew that :) – kaskelotti Oct 31 '13 at 20:33