使用Hibernate GORM时,如何将域类转换为JSON字符串?

使用Hibernate GORM时,如何将域类转换为JSON字符串?,json,hibernate,gorm,micronaut,Json,Hibernate,Gorm,Micronaut,为了在Micronaut 1.1.1中使用Hibernate GORM,我使用以下命令创建Micronaut应用程序: mn创建app foo-l=groovy-f=hibernate gorm 为了增加接近JSON的能力,我在build.gradle下面添加了一行,以便使用JsonSlurper接近JSON: 编译'org.codehaus.groovy:groovy-all:2.5.6' 因此,我的build.gralde如下所示: plugins { id "io.spring.d

为了在Micronaut 1.1.1中使用Hibernate GORM,我使用以下命令创建Micronaut应用程序:

mn创建app foo-l=groovy-f=hibernate gorm

为了增加接近JSON的能力,我在build.gradle下面添加了一行,以便使用JsonSlurper接近JSON:

编译'org.codehaus.groovy:groovy-all:2.5.6'

因此,我的build.gralde如下所示:

plugins {
    id "io.spring.dependency-management" version "1.0.6.RELEASE"
    id "groovy"
    id "com.github.johnrengelman.shadow" version "4.0.2"
    id "application"
}

version "0.1"
group "memberservice"

repositories {
    mavenCentral()
    maven { url "https://jcenter.bintray.com" }
}

dependencyManagement {
    imports {
        mavenBom 'io.micronaut:micronaut-bom:1.1.1'
    }
}

configurations {
    // for dependencies that are needed for development only
    developmentOnly 
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.5.6'
    compile "io.micronaut:micronaut-runtime-groovy"
    compile "io.micronaut:micronaut-validation"
    compile "io.micronaut:micronaut-http-client"
    compile "io.micronaut.configuration:micronaut-hibernate-validator"
    compile "io.micronaut.configuration:micronaut-hibernate-gorm"
    compile "io.micronaut:micronaut-http-server-netty"
    compileOnly "io.micronaut:micronaut-inject-groovy"
    runtime "ch.qos.logback:logback-classic:1.2.3"
    runtime "com.h2database:h2"
    runtime "org.apache.tomcat:tomcat-jdbc"
    testCompile("org.spockframework:spock-core") {
        exclude group: "org.codehaus.groovy", module: "groovy-all"
    }
    testCompile "io.micronaut:micronaut-inject-groovy"
    testCompile "io.micronaut.test:micronaut-test-spock"
}

test.classpath += configurations.developmentOnly

mainClassName = "memberservice.Application"
tasks.withType(GroovyCompile) {
    groovyOptions.forkOptions.jvmArgs.add('-Dgroovy.parameters=true')
}

shadowJar {
    mergeServiceFiles()
}

run.classpath += configurations.developmentOnly
run.jvmArgs('-noverify', '-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')
现在我有一个域类,如下所示:

import grails.gorm.annotation.Entity

@Entity
class Member {
    String memberId
    String email

    static constraints = {
        memberId    maxSize: 20, nullable: false, unique: true
        email       maxSize: 60, nullable: false
    }
}
import groovy.json.JsonBuilder
import groovy.util.logging.Slf4j
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import memberservice.domain.Member

@Slf4j
@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    def testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        def jsonObject = new JsonBuilder(member)
        log.info("check point 1001: finish JsonBuilder")
        String jsonString = jsonObject.toPrettyString()
        log.info("jsonString=" + jsonString)
        return jsonString
    }

    @Get('/buildSampleData')
    def buildSampleData() {
        Member member = new Member()
        member.with {
            memberId = 'A0001'
            email = 'foo@gmail.com'
        }
        Member.withTransaction {
            member.save()
//            new Member(memberId: 'A0002', 'foo1@mail.com').save()
//            new Member(memberId: 'A0003', 'foo2@mail.com').save()
        }
        return "Sample data built done"
    }
}
我有一个控制器,如下所示:

import grails.gorm.annotation.Entity

@Entity
class Member {
    String memberId
    String email

    static constraints = {
        memberId    maxSize: 20, nullable: false, unique: true
        email       maxSize: 60, nullable: false
    }
}
import groovy.json.JsonBuilder
import groovy.util.logging.Slf4j
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import memberservice.domain.Member

@Slf4j
@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    def testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        def jsonObject = new JsonBuilder(member)
        log.info("check point 1001: finish JsonBuilder")
        String jsonString = jsonObject.toPrettyString()
        log.info("jsonString=" + jsonString)
        return jsonString
    }

    @Get('/buildSampleData')
    def buildSampleData() {
        Member member = new Member()
        member.with {
            memberId = 'A0001'
            email = 'foo@gmail.com'
        }
        Member.withTransaction {
            member.save()
//            new Member(memberId: 'A0002', 'foo1@mail.com').save()
//            new Member(memberId: 'A0003', 'foo2@mail.com').save()
        }
        return "Sample data built done"
    }
}
以下是输出日志:

09:23:30.610 [pool-2-thread-1] INFO  m.controller.MemberController - member.email is foo@gmail.com
09:23:30.619 [pool-2-thread-1] INFO  m.controller.MemberController - check point 1001: finish JsonBuilder
09:23:31.069 [pool-2-thread-1] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: null
java.lang.StackOverflowError: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
at groovy.lang.MetaBeanProperty.getProperty(MetaBeanProperty.java:59)
at groovy.lang.PropertyValue.getValue(PropertyValue.java:42)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.getProperties(DefaultGroovyMethods.java:557)
at groovy.json.DefaultJsonGenerator.getObjectProperties(DefaultJsonGenerator.java:242)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:236)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
    .....
    .....
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:221)
at groovy.json.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:387)
at groovy.json.DefaultJsonGenerator.writeMap(DefaultJsonGenerator.java:375)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:237)
at groovy.json.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:164)
at groovy.json.DefaultJsonGenerator.writeIterator(DefaultJsonGenerator.java:402)
at groovy.json.DefaultJsonGenerator.writeArray(DefaultJsonGenerator.java:285)
似乎JsonSlurper和JsonBuilder都不能处理从GORM构建的域类

那么,在Micronaut中是否有任何优雅的方法可以将域类转换为JSON字符串呢?请不要要求我使用杰克逊图书馆,因为杰克逊的接近方式是如此迫切

我知道在Grails中,转换器JSON可以毫无问题地将域类转换为JSON字符串。那么,有没有可能像Grails一样将JSON转换器的功能添加到Micronaut中?

而不是这个

@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    def testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        def jsonObject = new JsonBuilder(member)
        log.info("check point 1001: finish JsonBuilder")
        String jsonString = jsonObject.toPrettyString()
        log.info("jsonString=" + jsonString)
        return jsonString
    }
}
你可以这样做

@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    Member testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        member
    }
}
如果控制器操作返回一个POJO/POGO/etc,它将使用Jackson序列化为JSON

仅供参考。。。我不会在控制器操作中执行
.withTransaction
操作,但这与提出的问题无关。

而不是这个

@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    def testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        def jsonObject = new JsonBuilder(member)
        log.info("check point 1001: finish JsonBuilder")
        String jsonString = jsonObject.toPrettyString()
        log.info("jsonString=" + jsonString)
        return jsonString
    }
}
你可以这样做

@Controller('/member')
class MemberController {


    @Get('/testFetchMember')
    Member testFetchMember() {
        Member member
        Member.withTransaction {
            member = Member.findByMemberId('A0001')
        }
        log.info("member.email is ${member.email}")
        member
    }
}
如果控制器操作返回一个POJO/POGO/etc,它将使用Jackson序列化为JSON


仅供参考。。。我不会在控制器操作中执行
.withTransaction
操作,但这与所提出的问题无关。

您不必麻烦使用Micronaut序列化。只要从控制器返回对象(确保添加对象返回类型),它就会自动为您序列化它(@products defaults为JSON)。@ToddSharp谢谢。它起作用了。但是,如果我的实体类包含一到多个子实体类,那么Micronaut会发生另一个错误:无法初始化代理[VipLevel#P7]-没有会话(通过引用链:Member[“VipLevel”]->VipLevel$HibernateProxy$apzZQbKm[“levelid”])尝试注释您的模型:您不必费心用Micronaut序列化。只要从控制器返回对象(确保添加对象返回类型),它就会自动为您序列化它(@products defaults为JSON)。@ToddSharp谢谢。它起作用了。但是,如果我的实体类包含一到多个子实体类,那么Micronaut会发生另一个错误:无法初始化代理[VipLevel#P7]-没有会话(通过引用链:Member[“VipLevel”]->VipLevel$HibernateProxy$apzZQbKm[“levelid”])尝试注释您的模型:Grails 4也是这样吗?具体来说,仅仅返回域实例就足够了吗?我不能在域上使用资源注释,因为我不希望搭建的控制器步进现有的控制器逻辑。(所以不让我@Jeff…“Grails 4也是这样吗?”-不。“我不能在域上使用资源注释,因为我不希望搭建的控制器踩到现有的控制器逻辑。”-
@Resource
是Grails的东西,但在Grails应用程序中,您可以使用它而不踩到现有的控制器逻辑。当您使用
@Resource
时,如果您还没有具有相应名称的控制器,我们仅在编译时为您生成一个控制器类。如果您这样做,将使用该控制器,而不是生成的控制器。常见的是提供您自己的扩展
RestfulController
。谢谢您的快速回复,杰夫!在我看来,它好像覆盖了控制器,但也许它覆盖了视图?我再试试。如果您有一个像
demo.Member
这样用
@grails.rest.Resource
注释的域类,并且您还有一个名为
demo.MemberController
的控制器,那么编译器扩展应该使用您的
demo.MemberController
,而不是生成一个。我无法重现您描述的行为,但如果可以,将该问题中的示例应用程序链接将非常有用。再次感谢您的反馈!Grails4也是这样吗?具体来说,仅仅返回域实例就足够了吗?我不能在域上使用资源注释,因为我不希望搭建的控制器步进现有的控制器逻辑。(所以不让我@Jeff…“Grails 4也是这样吗?”-不。“我不能在域上使用资源注释,因为我不希望搭建的控制器踩到现有的控制器逻辑。”-
@Resource
是Grails的东西,但在Grails应用程序中,您可以使用它而不踩到现有的控制器逻辑。当您使用
@Resource
时,如果您还没有具有相应名称的控制器,我们仅在编译时为您生成一个控制器类。如果您这样做,将使用该控制器,而不是生成的控制器。常见的是提供您自己的扩展
RestfulController
。谢谢您的快速回复,杰夫!在我看来,它好像覆盖了控制器,但也许它覆盖了视图?我再试试。如果您有一个像
demo.Member
这样用
@grails.rest.Resource
注释的域类,并且您还有一个名为
demo.MemberController
的控制器,那么编译器扩展应该使用您的
demo.MemberController
,而不是生成一个。我无法重现您描述的行为,但如果可以,将该问题中的示例应用程序链接将非常有用。再次感谢您的反馈!