Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I want to get a map of all the fields in a class (aka value object) in a generic way. The following works fine for me:

class Baz {
  String foo = "foo2"
  int bar = 2

  public Map asMap() {
    def map = [:] as HashMap
    this.class.getDeclaredFields().each {
      if (it.modifier == java.lang.reflect.Modifier.PRIVATE) {
        map.put(it.name, this[it.name])
      }
    }
    return map
  }
}

But this doesn't feel like the proper way. Is there a better approach?

share|improve this question

2 Answers

up vote 3 down vote accepted

Another alternative (very similar to Matt's) is to use the synthetic field property (which is set for default class properties, but not for your own defined props):

class Baz {
  String foo = "foo2"
  int bar = 2

  public Map asMap() {
    this.class.declaredFields.findAll { !it.synthetic }.collectEntries {
      [ (it.name):this."$it.name" ]
    }
  }
}
share|improve this answer
@neu242 as much I like having people choose my answer, the find criteria Tim is using is better. If you just look for properties with the modifiers bitmask equal to PRIVATE, you could miss properties that are (for example) private AND final. – Matt Passell Feb 24 '12 at 14:58
For the collectEntries expression, I'm using [it.name, this[it.name]] and you're using [(it.name):this."$it.name"]. It's interesting that it works with both a list and a map... – Matt Passell Feb 24 '12 at 15:02
1  
@MattPassell Yeah, collectEntries ends up calling the private addEntry method which deals with Maps and 2 element lists as separate cases (but with the same outcome) :-) – tim_yates Feb 24 '12 at 15:07
cool. I think I'll go with your approach in the future - feels more intuitive to specify it as a Map entry. Thanks! (this comment is supposed to start with @Tim, but it keeps getting trimmed off! StackExchange bug?) – Matt Passell Feb 24 '12 at 15:35
@MattPassell See I didn't realise you could do it the 2 element list way until you mentioned it, I missed it in your code! ;-) And as for the @Tim thing, I got a reply notification... the StackOverflow rules about when it does and doesn't let you put an @ are esoteric and seem to constantly shift, I always add it, then don't miss it when it's gone ;-) – tim_yates Feb 24 '12 at 15:51

Here's one alternative:

class Baz {
  String foo = 'foo2'
  int bar = 2

  public Map asMap() {
    this.class.declaredFields.findAll { it.modifiers == java.lang.reflect.Modifier.PRIVATE }.
      collectEntries { [it.name, this[it.name]] }
  }
}

Basically, I'm finding just the fields with the modifiers value set to private and then collecting those as Map entries.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.