将JSON中找到的自定义字符串映射到POGO枚举案例

时间:2018-10-16 12:44:01

标签: json groovy enums mapping jsonslurper

在Grails应用程序的上下文中,我们将JSON解析为命令对象。从JSON映射到POGO的自动转换失败,并显示以下错误:

  

org.codehaus.groovy.runtime.typehandling.GroovyCastException
  由于以下原因,无法将类别为“ {<snip>}”的对象“ groovy.json.internal.LazyMap”转换为类别“ SomeCmd”的对象:
  java.lang.IllegalArgumentException:没有枚举常量Foo.my-bar

我将其范围缩小到普通的Groovy MWE:

import groovy.json.JsonSlurper

enum Foo {
    Bar("my-bar"),
    Ista("my-ista")

    final String s

    private Foo(String s) {
        this.s = s
    }
}

class SomeCmd {
    Foo foo
}

def some = new SomeCmd(new JsonSlurper().parseText('{ "foo" : "my-bar" }'))
println(some.foo)

此错误

  

java.lang.IllegalArgumentException:没有枚举常量Foo.my-bar

这是预期的-到目前为止,很好。

现在,在the documentation之后,我认为从StringFoo添加自定义强制可能会解决该问题(也来自here):

enum Foo {
    <snip>

    static Foo fromJsonString(String s) {
        return values().find { it.s == s }
    }
}

def oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = { Class type ->
    type == Foo ?
            Foo.byJsonString(delegate as String) :
            oldAsType.invoke(delegate, [type] as Class[])
}

但是,错误仍然存​​在。显然,JsonSlurper完全不使用强制,因为

println("my-bar" as Foo)

根据需要打印Bar

这是怎么回事?如何获得JsonSlurper来根据案件名称​​除了来选择正确的枚举案件?


PS:有趣的是,如果我们将倒数第二行更改为

new JsonSlurper().parseText('{ "foo" : "my-bar" }') as SomeCmd

脚本打印null

1 个答案:

答案 0 :(得分:0)

Groovy将很乐意使用自定义设置器来构造对象。使用问题中给出的Foo.fromJsonString,如下定义SomeCmd

class SomeCmd {
    Foo foo

    void setFoo(Object jsonObject) {
        if (jsonObject == null || jsonObject instanceof Foo) {
            this.foo = jsonObject
            return
        } else if (jsonObject instanceof String) {
            Foo f = Foo.fromJsonString(jsonObject)
            if ( null != f ) {
                this.foo = f
                return
            }
        }

        throw new IllegalArgumentException("No Foo for $jsonObject")
    }
}

然后,给定的代码将根据需要打印Bar

但是,这在Grails中无法将JSON解析为命令对象-Grails既不使用强制也不使用Groovy的地图“魔术”。参见this follow-up question