【问题标题】:Mapping custom strings found in JSON to POGO enum cases将 JSON 中的自定义字符串映射到 POGO 枚举案例
【发布时间】:2018-10-16 12:44:00
【问题描述】:

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

org.codehaus.groovy.runtime.typehandling.GroovyCastException:
无法将具有类“groovy.json.internal.LazyMap”的对象“{<snip>}”转换为类“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 之后,我认为将自定义强制从 String 添加到 Foo 可能会解决问题(也来自 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

【问题讨论】:

    标签: json groovy enums mapping jsonslurper


    【解决方案1】:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2013-04-05
      相关资源
      最近更新 更多