web-dev-qa-db-ja.com

Grailsは子ドメインオブジェクトを取得します

私は2つのドメインクラスがあり、1つは親でもう1つは子であり、それらの間にhasMany関係があります。親クラスには多くの子があり、子クラスは親クラスに属しています。そして、ここにコーディング例があります。

class Parent{
   String name
    static hasMany = [childs:Child] 
    static constraints = {
   }
}


class Child{
   String name
   static belongsTo = [parent:Parent]
   static constraints={}
}

問題は、親オブジェクトを取得するとすぐに、親クラスに関連付けられた子オブジェクトもフェッチされることです。しかし、オブジェクトをJSONに変換すると、子オブジェクトが完全に表示されず、子オブジェクトのIDしか表示できません。 Idだけでなく、子オブジェクトのすべての列を表示したい。

変換されたJSON応答:

[{"class":"project.Parent","id":1,
  "name":"name1","childs":[{"class":"Child","id":1},{"class":"Review","id":2}]}]

しかし、次のように、子オブジェクトの名前も含む応答が必要です

[{"class":"project.Parent","id":1,"name":"name1",
  "childs":[{"class":"Child","id":1,"name":"childname1"},
            {"class":"Review","id":2,"name":"childname2"}
           ]
}]

どんな助けでも大歓迎です。前もって感謝します。

28
Chaman

問題は、デフォルトのJSONコンバーターの使用にあります。オプションは次のとおりです。

 1. Default  -  all fields, shallow associations
    a. render blah as JSON

 2. Global deep converter - change all JSON converters to use deep association traversal
    a. grails.converters.json.default.deep = true

 3. Named config marshaller using provided or custom converters
    a. JSON.createNamedConfig('deep'){
        it.registerObjectMarshaller( new DeepDomainClassMarshaller(...) )
    }
    b. JSON.use('deep'){
        render blah as JSON
    }

 4. Custom Class specific closure marshaller 
    a. JSON.registerObjectMarshaller(MyClass){ return map of properties}
    b. render myClassInstance as JSON

 5. Custom controller based closure to generate a map of properties
    a. convert(object){
        return map of properties
    }
    b. render convert(blah) as JSON

現在、デフォルトのオプション1を使用しています。

最も簡単な方法は、オプション2を使用してグローバルディープコンバーターを設定することですが、これはアプリのすべてのドメインクラスに影響することに注意してください。つまり、最上位のオブジェクトで終了する大きな関連付けのツリーがあり、それらの最上位のオブジェクトのリストを変換しようとすると、ディープコンバーターはすべてのクエリを実行して、関連するすべてのオブジェクトと関連するオブジェクトをフェッチします。順番。 -データベース全体を一度にロードできます :)注意してください。

55
dbrin

最新のGrailsは自動的にディープコンバージョンしますが、おそらく遅延読み込みの犠牲者です。

子はアクセス時にロードされないため、JSONコンバーターは子をJSONに変換できません。回避策はこれを置くことです

静的マッピング= {怠惰な子供:false}

3
Ganesh Krishnan

ユーザーdbrinは正しいですが、もう1つのオプションがあります。 GrailsGSONプラグインを使用することもできます。

https://github.com/robfletcher/grails-gson#readme

プラグインは、jsonデータを処理するときにいくつかの機能を追加します。

1
mburri

提案された解決策は機能していますが、「grailsApplication」を参照するのに問題がありました。他のサービスと同じように摂取できることがわかりました。次のコードを

BootStrap.groovy

ファイル。また、クラスDeepDomainClassMarshallerは双方向の循環参照を非常に適切に処理しますが、JSONペイロードは完全に深化した後では大きくなりません。

package aisnhwr

import grails.converters.JSON
import grails.core.GrailsApplication
import org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller

class BootStrap {

    GrailsApplication grailsApplication

    def init = { servletContext ->
        JSON.createNamedConfig('deep'){
            it.registerObjectMarshaller( new DeepDomainClassMarshaller(false, grailsApplication) )
        }
    }
    def destroy = {
    }
}
0
user2078148