Grails 5 DeepDomainClassMarshaller JSON 因循环引用和空值而失败

问题描述 投票:0回答:1

大家好,我正在尝试使用 Grails JSON 功能从域类生成 json。 我在这方面面临着许多问题。

如果有人可以在这里帮助我,那就太好了。我有以下 grails 配置

grailsVersion=5.3.2
grailsGradlePluginVersion=5.3.0
groovyVersion=3.0.11
gorm.version=7.3.3

我有以下 3 个领域类。

公司.groovy

class Company{

    String name

    String contactName

    String agentId // If businessType = Accountant
    String status  = "Active"


    User owner
    User lastUpdatedBy


    static hasMany = [apps: ZApp]
  
}

User.groovy

class User {

    Long id

    String fullName
    String username
    User owner
    User lastUpdatedBy
}

和 ** ZApp.groovy**

class ZApp{

    String appName

    String appDescription
}

我在 application.groovy 文件中为深域编组器添加了以下行。

grails.converters.json.default.deep = true

然后我尝试为公司实例生成 json,如下所示

公司为 JSON

我收到以下错误

引起:org.grails.web.converters.exceptions.ConverterException:java.lang.StringIndexOutOfBoundsException:开始0,结束-1,长度0

当我检查错误跟踪时,它在 JSON.java 文件中的以下行中给出错误

enter image description here

我认为这应该自动优雅地处理它。但不,我在 application.groovy

中添加以下行

grails.converters.json.circular.reference.behaviour='路径'

错误已解决,但现在只要任何字段具有空值就会出现错误。在我的例子中,公司类的agentId为null

引起:org.grails.web.converters.exceptions.ConverterException:org.grails.web.json.JSONException:值不按顺序:预期模式为 OBJECT 或 ARRAY 当写入 'org.grails.web.json.JSONWriter$NullWritable@1a1fd03d' 时,但处于 INIT

来自 DomainClassMarshaller.java 的以下代码出现错误

if ( !(property instanceof Association) ) {
                // Write non-relation property
                Object val = beanWrapper.getPropertyValue(property.getName());
                json.convertAnother(val); // **here it throws error**
            }

为了绕过这个错误,我创建了自己的 CustomDomainMarshaller 类并代替

json.convertAnother(val);我用过

if (val == null) {
   writer.value(null)
} else {
   json.convertAnother(val);
}

而且它奏效了。 但现在我遇到了另一个应用程序错误(ZApp 的 Hasmany 关系)

引起:java.lang.ClassCastException:类org.grails.web.json.PathCapturingJSONWriterWrapper$PropertyElement无法转换为类org.grails.web.json.PathCapturingJSONWriterWrapper$IndexElement(org.grails.web.json.PathCapturingJSONWriterWrapper$ PropertyElement 和 org.grails.web.json.PathCapturingJSONWriterWrapper$IndexElement 位于加载程序“app”的未命名模块中)

当应用程序中有 2 个项目时,就会出现此错误。当调用第二项时。 以下代码出现错误。

    @SuppressWarnings(["unchecked", "rawtypes"])
    public void marshalObject(Object value, JSON json) throws ConverterException {
        JSONWriter writer = json.getWriter();
        value = proxyHandler.unwrapIfProxy(value);
        Class<?> clazz = value.getClass();

        List<String> excludes = json.getExcludes(clazz);
        List<String> includes = json.getIncludes(clazz);
        IncludeExcludeSupport<String> includeExcludeSupport = new IncludeExcludeSupport<String>();

        BeanWrapper beanWrapper = new BeanWrapperImpl(value);

        writer.object(); // **here it throws error**

并且在邮递员中收到以下 json 响应。

{
    "data": [
        {
            "id": 72050630615,
            "lastUpdatedBy": {
                "id": 59396476865
            },
            "dateCreated": "2024-03-30 18:07:42",
            "contactName": "Chetan",
            "lastUpdated": "2024-05-22 18:54:21",
            "agentId": null,
            "apps": [
                {
                    "id": 2,
                    "appName": "ZUCODU MTD SERVICES",
                    "appDescription": "Use this app to file you tax using Zucodu MTD app"
                }{
                    "message": "Internal server error",
                    "error": 500
                }
json groovy grails
1个回答
0
投票

问题在于您的

User
引用了自身,这可能会导致循环。
hasMany
关系也存在问题,因为 Grails 总是以某种方式搞砸了。

我们遇到了类似的问题,因此我们选择不直接在域类上使用 JSON 解析。相反,我们开始使用 DTO 类,将数据解析为“非工件”类。这是最佳实践,可以避免 Grails 出现意外行为。

我知道它不能解决你想要做的事情,但我认为值得考虑。

© www.soinside.com 2019 - 2024. All rights reserved.