Search code examples
jsoncollectionsgroovyenumstype-coercion

Type coercion of collection of strings into collection of enums in Groovy


In cases where I want to parse from JSON into a domain object I have defined to contain a collection of enums I have found that Groovy does not coerce the contents of the collection automatically, which I suppose shouldn't be expected anyway as generics are a compile-time concern.

If I naively do type coercion on the parsed JSON my collections will contain strings at runtime, which will make comparisons of the collection elements with enums fail regardless of value.

An alternative is to override the setter for the enum collection and do coercion on each element. This is illustrated in the below example.

import groovy.json.*

enum Hero {
    BATMAN, ROBIN
}

class AClass {

    Collection<Hero> heroes
}

class BClass {

    Collection<Hero> heroes

    void setHeroes(Collection heroes){
        this.heroes = heroes.collect { it as Hero }
    }
}

class CClass {

    AClass a
    BClass b
}

def json = '''
    {
        "a":
        {
            "heroes":["BATMAN", "ROBIN"]
        },
        "b":
        {
            "heroes":["BATMAN", "ROBIN"]
        }
    }

'''

def c = new JsonSlurper().parseText(json) as CClass

assert c.a.heroes[0].class == String
assert c.b.heroes[0].class == Hero 

The overridden setter approach solves my problem, but it seems that it's a bit vanilla, and I was wondering if Groovy supports a smarter way of propagating the type coercion.


Solution

  • I don't know of a better way currently. We could write an external visitor kind of processor for the JsonSlurper result, but that would be more code