4

Grails にはデータ バインディングに関するバグがあり、不正な数値入力を処理しているときにキャスト例外がスローされます。ジラ: http://jira.grails.org/browse/GRAILS-6766

これを修正するために、次のコードを作成して、にある POGO クラスの数値入力を手動で処理しFooました。src/groovy

void setPrice(String priceStr)
{
    this.priceString = priceStr

    // Remove $ and , 
    priceStr = priceStr.trim().replaceAll(java.util.regex.Matcher.quoteReplacement('$'),'').replaceAll(',','')

    if (!priceStr.isDouble()) {
        errors.reject(
            'trade.price.invalidformat',
            [priceString] as Object[],
            'Price:[{0}] is an invalid price.')

        errors.rejectValue(
            'price',
            'trade.price.invalidformat')
    } else {
        this.price = priceStr.toDouble();
    }
}

次の行では、null 参照例外がスローされますerrors.reject()

foo.price = "asdf" // throws null reference on errors.reject()
foo.validate()

ただし、次のように言えます。

foo.validate()
foo.price = "asdf" // no Null exception
foo.hasErrors() // false
foo.validate()
foo.hasErrors() // true

validate()が呼び出されたときのエラーはどこから来るのですか? 最初errorsに呼び出さずにプロパティを追加する方法はありますか?validate()

4

3 に答える 3

6

理由は正確にはわかりませんが、プロパティのようgetErrors()にアクセスするのではなく、明示的に呼び出す必要がありerrorsます。何らかの理由で、Groovyはそのメソッドを呼び出していません。したがって、reject行をにsetPrice()変更します

getErrors().reject(
        'trade.price.invalidformat',
        [priceString] as Object[],
        'Price:[{0}] is an invalid price.')

getErrors().rejectValue(
        'price',
        'trade.price.invalidformat')

Errorsこれは、オブジェクトがメソッドに存在することを確認する最も簡単な方法です。ドメインクラスに検証関連のメソッドを追加するコードを確認できます。

于 2013-03-11T22:31:02.387 に答える
5

AST変換処理@Validateable は、とりわけクラスを拡張します

  • 名前の付いたフィールドerrors
  • パブリックメソッドgetErrors、、、setErrorsおよびclearErrorshasErrors

まだ設定されていない場合、メソッドはフィールドをgetErrors遅延設定します。したがって、同じクラス内へのアクセスは、Java Beanプロパティアクセスではなくフィールドアクセスとして扱われ、遅延初期化をバイパスしてerrorsいるように見えます。errors

したがって、修正getErrors()は単にの代わりに使用することであるように見えますerrors

于 2013-03-11T22:44:07.527 に答える
2

エラーは、検証可能なクラス(ドメインクラスとアノテーションを持つクラス@Validateable)に動的に追加されます。

開発者が数値の代わりに文字列を設定できるようにするのは、良い方法ではないようです。また、検証はその特定のクラスに対してのみ機能します。

より良いアプローチは、数値のカスタムプロパティエディタを登録することだと思います。これは、 (フォームからの)からdd / MM/yyyyのような形式への変換を可能にする日付の例です。番号が解析可能であることを強制するので(たとえば、例外をスローする)、考え方は同じです。StringDateInteger.parseInt()

ドメインクラスでは、文字列の代わりに数値タイプを使用します。これにより、コード開発者は数値以外の値を格納できなくなります。

于 2013-03-11T22:29:32.947 に答える