从 JsonSlurper 向对象添加强类型

Add strong typing to objects from JsonSlurper

我在使用 Groovy 中的 JsonSlurper 打字时遇到了一些问题。我对 Groovy 还很陌生,对向它添加强类型更陌生 - 请耐心等待。

现在我已经创建了一个 trait,它定义了我的 JSON 对象的一般形状,我正在尝试将 parseText 的结果投射到它。

import groovy.json.JsonSlurper

trait Person {
    String firstname
    String lastname
}

def person = (Person)(new JsonSlurper().parseText('{"firstname": "Lando", "lastname": "Calrissian"}'))

println person.lastname

这抛出

Exception in thread "main" org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '{firstname=Lando, lastname=Calrissian}' with class 'org.apache.groovy.json.internal.LazyMap' to class 'Person' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: Person(org.apache.groovy.json.internal.LazyMap)
    ...

我明白为什么我的代码没有意义,我不是要更改数据类型(转换),我只是想让我的 IDE 知道这是我的对象里面有什么。

是否可以至少向我的 JSON 对象添加代码完成? 我也很想进行运行时类型检查,但这不是必需的.

这实际上一个演员,Groovy会尝试将您的地图变成所述对象。

来自docs

The coercion operator (as) is a variant of casting. Coercion converts object from one type to another without them being compatible for assignment.

POJO 的工作方式是使用 Map-c'tor 构造一个新对象。这将展开调用 setter 或直接使用静态编译。

请注意,使用带有过多键的地图会导致错误。所以我只会将其用于玩具项目。使用适当的 JSON-mapper ,例如取而代之的是杰克逊。

所以这里的解决方案是不使用特征(基本上是一个接口),而是使用常规 class.

你可以尝试使用委托

这允许将 class 环绕在地图

周围
import groovy.json.JsonSlurper

class Person {
    @Delegate Map delegate
    String getFirstname(){ delegate.get('firstname') }
    String getLastname(){ delegate.get('lastname') }
}

def person = new Person(delegate:new JsonSlurper().parseText('{"firstname": "Lando", "lastname": "Calrissian"}'))

println person.lastname

或者例如使用 Gson 进行解析:

@Grab(group='com.google.code.gson', module='gson', version='2.8.5')

import com.google.gson.Gson

class Person {
    String firstname
    String lastname
}

def person = new Gson().fromJson('{"firstname": "Lando", "lastname": "Calrissian"}', Person.class)

assert person instanceof Person
println person.lastname