Сопоставление пользовательских строк, найденных в JSON, с перечислениями POGO - PullRequest
0 голосов
/ 16 октября 2018

В контексте приложения 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)

Thisошибки с

java.lang.IllegalArgumentException: нет константы перечисления Foo.my-bar

Это ожидается - пока, так хорошо.

Теперь, после документация , я думал, что добавление пользовательского принуждения с String до Foo может решить проблему (также с здесь ):

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 голосов
/ 06 ноября 2018

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.См. следующий вопрос .

...