Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy object properties in map

Tags:

groovy

Instead of having to declare all the properties in a map from an object like:

prop1: object.prop1

Can't you just drop the object in there like below somehow? Or what would be a proper way to achieve this?

results: [
    object, 
    values: [
        test: 'subject'
    ]
]
like image 250
groovy Avatar asked Mar 17 '16 21:03

groovy


Video Answer


2 Answers

object.properties will give you a class as well

You should be able to do:

Given your POGO object:

class User {
    String name
    String email
}

def object = new User(name:'tim', email:'[email protected]')

Write a method to inspect the class and pull the non-synthetic properties from it:

def extractProperties(obj) {
    obj.getClass()
       .declaredFields
       .findAll { !it.synthetic }
       .collectEntries { field ->
           [field.name, obj."$field.name"]
       }
}

Then, map spread that into your result map:

def result = [
    value: true, 
    *:extractProperties(object)
]

To give you:

['value':true, 'name':'tim', 'email':'[email protected]']
like image 122
tim_yates Avatar answered Sep 24 '22 19:09

tim_yates


If you don't mind using a few libraries here's an option where you convert the object to json and then parse it back out as a map. I added mine to a baseObject which in your case object would extend.

class BaseObject {
  Map asMap() {
    def jsonSlurper = new groovy.json.JsonSlurperClassic()
    Map map = jsonSlurper.parseText(this.asJson())
    return map
  }
  String asJson(){
    def jsonOutput = new groovy.json.JsonOutput()
    String json = jsonOutput.toJson(this)
    return json
  }
}

Also wrote it without the json library originally. This is like the other answers but handles cases where the object property is a List.

class BaseObject {
Map asMap() {
    Map map = objectToMap(this)
    return map
}   
def objectToMap(object){
    Map map = [:]
    for(item in object.class.declaredFields){
        if(!item.synthetic){
            if (object."$item.name".hasProperty('length')){
                map."$item.name" = objectListToMap(object."$item.name")
            }else if (object."$item.name".respondsTo('asMap')){
                map << [ (item.name):object."$item.name"?.asMap() ]
            } else{
                map << [ (item.name):object."$item.name" ]
            }
        }
    }
    return map
}

def objectListToMap(objectList){
    List list = []
    for(item in objectList){
        if (item.hasProperty('length')){
            list <<  objectListToMap(item)
        }else {
            list << objectToMap(item)
        }
    }
    return list
}
}
like image 30
Drundage Avatar answered Sep 22 '22 19:09

Drundage