Created
December 9, 2019 18:09
-
-
Save tonyerskine/025d586118ef242647ee1ec1c56a13ac to your computer and use it in GitHub Desktop.
Groovy/Grails ToMap Trait: Convert POGO to Map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This Trait adds a ToMap(..) methods to a POGO, which convert the object to a Map<String, Object> | |
* ignoring extraneous fields such as synthetic, static, grails domain classes, and collections. | |
* It is designed to be used preprocess Grails domain object proir to converting to JSON. However, | |
* it does not require Grails to work. | |
*/ | |
import groovy.transform.InheritConstructors | |
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler | |
import org.springframework.validation.Errors | |
import java.lang.reflect.Field | |
import java.lang.reflect.Modifier | |
trait ToMap { | |
static transients = ["defaultMappedFields", "excludedFields"] | |
private List<String> defaultMappedFields | |
private List<String> excludedFields = ["grailsApplication"] | |
List<String> getExcludedFields() { excludedFields } | |
void setExcludedFields(List<String> excludedFields) { this.excludedFields = excludedFields } | |
List<String> getDefaultMappedFields() { | |
defaultMappedFields ?: this.class.declaredFields.findAll { field -> | |
!field.synthetic && | |
!DomainClassArtefactHandler.isDomainClass(field.type) && | |
!Modifier.isStatic(field.modifiers) && | |
![Set, List, Map, Errors].contains(field.type) && | |
!excludedFields.contains(field.name) | |
}*.name | |
} | |
void setDefaultMappedFields(List<String> defaultFields) { | |
defaultFields.each { | |
Field field = this.class.getDeclaredField(it) | |
if (DomainClassArtefactHandler.isDomainClass(field.type)) { | |
throw new InvalidDefaultMappedFieldException("$it cannot be set as a default mapped field because it is a domain object. Only simple fields can be set as default fields to prevent circular references, etc.") | |
} | |
if ([Set, List, Map, Errors].contains(field.type)) { | |
throw new InvalidDefaultMappedFieldException("$it cannot be set as a default mapped field because it is a collection or map. Only simple fields can be set as default fields to prevent circular references, etc.") | |
} | |
if (excludedFields.contains(field.name)) { | |
throw new InvalidDefaultMappedFieldException("$it cannot be set as a default mapped field because it is explicitly excluded in excludedFields: $excludedFields") | |
} | |
} | |
this.defaultMappedFields = defaultFields | |
} | |
Map toMap() { | |
getDefaultMappedFields().collectEntries { fieldName -> | |
[(fieldName): this."$fieldName"] | |
} | |
} | |
Map toMap(List<String> include) { | |
Map map = toMap() | |
include.each { | |
map[it] = this[it].toMap() | |
} | |
return map | |
} | |
} | |
@InheritConstructors | |
class InvalidDefaultMappedFieldException extends RuntimeException { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment