Grails доступ к вложенным полям с помощью gstrings

#grails #groovy #gstring

#grails #groovy #gstring

Вопрос:

Я пытаюсь получить доступ к вложенному полю с помощью gstring, но он выдает исключение groovy.lang.MissingPropertyException

У меня есть два класса

 Class Person{
   Address address
}
Class Address{
  String city
}
  

Где-то в моем коде я делаю,

 def person = Person.get(1)
def field = "address.city"
def city = person."${field}"
  

Строка, в которой я пытаюсь получить город от person, вызывает исключение groovy.lang.MissingPropertyException

Если я попытаюсь получить прямое свойство с помощью gstring, оно сработает, но приведенный выше код не работает.

Любая помощь?

Ответ №1:

Здесь вы пытаетесь получить доступ к свойству по имени address.city , которое равно person."address.city" , что означает, что точка здесь рассматривается как часть имени свойства, а не как разделитель доступа, как вы ожидаете. Следующий код должен разрешить ваше свойство:

 def city = field.tokenize('.').inject(person) {v, k -> v."$k"}
  

Комментарии:

1. Это действительно элегантное решение!

2. Как вы устанавливаете значение вложенного свойства, полученного таким образом?

3. @user1200125 Таким образом, вы получаете не ссылку на свойство, а его значение, поэтому устанавливать значение не для чего.

4. есть идеи о том, как получить свойство / поле, чтобы затем изменить его значение?

5. @user1200125 Нет, я уже больше года не работаю. Но вы, безусловно, можете открыть специальный вопрос. Я думаю, что вы ищете отражение.

Ответ №2:

Я думаю, что проблема связана с оператором dot для доступа к вложенному свойству.

Это работает:

 class Person{
   String address
}

def person = new Person(address:'Madrid')

def field = 'address'
assert 'Madrid' == person."${field}"
  

Это работает:

 class Person{
   Address address
}

class Address {
  String city
}

def person = new Person(address: new Address(city: 'Madrid'))

def field = 'address'
def subField = 'city'
assert 'Madrid' == person."${field}"."${subField}"
  

Комментарии:

1. Хотя я согласен с тем, что другой ответ Никиты Волкова, def city = field.tokenize(‘.’).inject(person) {v, k -> v.»$k»}, ЯВЛЯЕТСЯ ОЧЕНЬ элегантным ответом, я предпочитаю простоту и удобочитаемость этого ответа. На первый взгляд, этот ответ понятен.