MBozic
MBozic

Reputation: 1192

Grails Enumeration to JSON

I would like to change the way enums are marshalled to JSON. I am currently using default grails.converters.JSON ( as JSON) and for example in controller I use:

FilmKind.values() as JSON

The output of this is:

"kind":[{"enumType":"FilmKind","name":"DRAMA"},{"enumType":"FilmKind","name":"ACTION"}]

I would like to remove "enumType" and just return:

"kind":["DRAMA","ACTION"]

I am looking for a solution which would still allow me to use

as JSON

because I don't want to marshall each enumeration individually.

Upvotes: 5

Views: 4148

Answers (4)

Robbert
Robbert

Reputation: 335

In case anyone is wandering how to convert all enum values to plain String values in a generic way:

class EnumTypeHidingJSONMarshaller {
    void register() {
        JSON.registerObjectMarshaller(Enum) { Enum someEnum ->
            someEnum.toString()
        }
    }
}

Upvotes: 17

user800014
user800014

Reputation:

How about:

def display = [kind:[]]
FilmKind.values().each { val ->
  display.kind.add(val.value)
}

render display as JSON

Upvotes: 1

Gregg
Gregg

Reputation: 35864

because I don't want to marshall each enumeration individually.

Well, unless you want to write your own JSON converter, marshalling is the best approach here. Reason is because the only real other way is to do what Sergio is suggesting and you'll have to call that code everywhere you need it. And if FilmKind is a property of another class then his solution won't work at all really.

I would suggest Marshallers and here is how I would do it. Create a class called FilmKindMarsaller:

class FilmKindMarshaller {
  void register() {
    JSON.registerObjectMarshaller(FilmKind) { FilmKind filmKind ->
      [
          name: filmKind.toString()

      ]
    }
  }
}

Then add the following to your Bootstrap:

[ new FilmKindMarshaller() ].each { it.register() }

The above is so that you can just keep adding instances of each Marshaller you need.

Now, anytime FilmKind is JSON'ified, be that on its own or part of a parent class, you get the JSON you want, sans enumType.

Upvotes: 12

doelleri
doelleri

Reputation: 19682

You can register a custom object marshaller for your domain class to allow as JSON. In your Bootstrap.groovy, you can do something like this:

JSON.registerObjectMarshaller(FilmKind) {
    def result = [:]
    def props = ['name']
    props.each { prop ->
        result[prop] = it."$prop"
    }
    result
}

Upvotes: 3

Related Questions