1

JSON.parse(someJSON)の結果をカスタムドメインクラスでもあるメンバーに自動的に変換するようにドメインクラスに教えたいと思います。

これらのドメインクラスが与えられた場合:

class Person {
    Long id
    String name

    static hasMany = [aliases: PersonAlias]
}

class PersonAlias {
    Person person
    Long id
    String name
}

そして、いくつかのPersonAliasesを持つPersonを表すこのJSON:

{
     "id":20044397,
     "name":"John Smith",
     "aliases":[{"id":13376,"name":"Johnny Smith"},{"id":13377,"name":"J. Smith"}]
}

コントローラを次のようにシンプルに保ちたい:

class PersonController {
    def saveViaAjax = {
        def props = JSON.parse(params.JSON)
        Person p = Person.get(props.id)
        p.properties = props
        p.save(flush: true)
    }
}

しかし悲しいことに、私はこのエラーを受け取ります:

タイプ'org.codehaus.groovy.grails.web.json.JSONArray'のプロパティ値をプロパティ'aliases'に必要なタイプ'java.util.Set'に変換できませんでした。ネストされた例外はjava.lang.IllegalStateExceptionです:タイプ[org.codehaus.groovy.grails.web.json.JSONObject]の値をプロパティ'aliases [0]'に必要なタイプ[heavymeta.PersonAlias]に変換できません:一致するエディターがないか、変換戦略が見つかりました

そこで、JSONデータをPersonAliasインスタンスに自動的に変換する方法をドメインクラスに教えたいと思います。ドメインオブジェクトに渡す前に、コントローラーでデータをフォーマットしないようにしたいと思います。これらの目標を達成するにはどうすればよいですか?

4

3 に答える 3

1

bindUsingアノテーションを使用し、カスタムバインディングコードを提供して、jsonをバインドされているプロパティに変換できます。

class Person {
    Long id
    String name

    @BindUsing({obj, source ->
       List retVal = [] 
       def aliases = source['aliases']
       if(aliases) {
           aliases.each { 
             retVal << new PersonAlias(name:it.name)
           }
       } 
       return retVal
    })
    List<PersonAlias> aliases

    static hasMany = [aliases: PersonAlias]
}
于 2015-03-27T08:03:42.340 に答える
0

私はこのプラグインを考えています:https ://github.com/pedjak/grails-marshallersはあなたが探していることをするかもしれませんか?私はそれを自分で試したことはありません。

于 2012-08-07T05:06:49.677 に答える
0

私もこの問題に遭遇しました-私は自分のウェブサイトで修正を文書化するために最善を尽くしました-http://dalelotts.com/software-architect/grailsを参照してください

一般的な解決策は、JSONをデータバインディングに使用できるパラメーターマップに変換することです。JSON用のアノテーション駆動型DomainClassMarshallerを含む、サイトの詳細情報

protected Object readFromJson(Class type, InputStream entityStream, String charset) {

   def mapper = new ObjectMapper();
   def parsedJSON = mapper.readValue(entityStream, typeRef);

   Map<String, Object> map = new HashMap<>();

   parsedJSON.entrySet().each {Map.Entry<String, Object> entry ->
       if (List.isAssignableFrom(entry.getValue().getClass())) {

           List values = (List) entry.getValue();
           int limit = values.size()
           for (int i = 0; i <  limit; i++) {
               final theValue = values.get(i)
               map.put(entry.key + '[' + i + ']', theValue)

               appendMapValues(map, theValue, entry.key + '[' + i + ']' )

           }
       } else {
           map.put(entry.key, entry.value);
       }
   }

   def result = type.metaClass.invokeConstructor(map)


   // Workaround for http://jira.codehaus.org/browse/GRAILS-1984
   if (!result.id) {
       result.id = idFromMap(map)
   }
   result
}

private void appendMapValues(Map<String, Object> theMap, Object theValue, String prefix) {
    if (Map.isAssignableFrom(theValue.getClass())) {

        Map<String, Object> valueMap = (Map<String, Object>) theValue;

        for (Map.Entry<String, Object> valueEntry : valueMap.entrySet()) {
            theMap.put(prefix + '.' + valueEntry.key, valueEntry.value)
            appendMapValues(theMap, valueEntry.value, prefix + '.' + valueEntry.key)
        }
    }
}
于 2012-08-21T11:40:57.660 に答える