2012-07-03 24 views
21

現在、私はSpringベースのWebアプリケーションからJSON結果を送信するためにJacksonを使用しています。Java to Jackson JSONシリアライゼーション:Moneyフィールド

私が抱えている問題は、すべてのお金フィールドを小数点以下2桁で出力することです。 25.50などの数値が25.5などに切り捨てられているので、setScale(2)を使用してこの問題を解決できませんでした。

他に誰かがこの問題に対処していますか?カスタムJacksonシリアライザを使ってMoneyクラスを作成することを考えていました...フィールド変数のカスタムシリアライザを作成できますか?あなたはおそらく...でも、それでも顧客シリアライザに小数点以下2桁の数字を追加するにはどうしたらいいですか?

+0

これらの値は何に保存していますか? BigDecimal? –

+0

@GregKopffはいa BigDecimal – ControlAltDel

答えて

5

私は同じ問題を抱えていましたが、代わりにJSONをStringとしてフォーマットしました。ハックのビットかもしれませんが、実装するのは簡単です。代わりに、各部材に@JsonSerializeを設定したり、特定のタイプのために、カスタマー・シリアライザを使用するモジュール構成できゲッター

private BigDecimal myValue = new BigDecimal("25.50"); 
... 
public String getMyValue() { 
    return myValue.setScale(2, BigDecimal.ROUND_HALF_UP).toString(); 
} 
40

moneyフィールドでカスタムシリアライザを使用できます。次に、MoneyBeanの例を示します。フィールドの数値は、@JsonSerialize(= =を使用)で注釈が付けられます。

public class MoneyBean { 
    //... 

    @JsonProperty("amountOfMoney") 
    @JsonSerialize(using = MoneySerializer.class) 
    private BigDecimal amount; 

    //getters/setters... 
} 

public class MoneySerializer extends JsonSerializer<BigDecimal> { 
    @Override 
    public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException, 
      JsonProcessingException { 
     // put your desired money style here 
     jgen.writeString(value.setScale(2, BigDecimal.ROUND_HALF_UP).toString()); 
    } 
} 

これだけです。 BigDecimalが正しい方法で印刷されるようになりました。私は単純なテストケースを使って表示しました。

@Test 
public void jsonSerializationTest() throws Exception { 
    MoneyBean m = new MoneyBean(); 
    m.setAmount(new BigDecimal("20.3")); 

    ObjectMapper mapper = new ObjectMapper(); 
    assertEquals("{\"amountOfMoney\":\"20.30\"}", mapper.writeValueAsString(m)); 
} 
+1

良いアプローチですが、JSON出力の数値型ではなく文字列として出力します。 – jro

+17

ビジネスの観点から見ると、これはひどいアプローチです。シリアライズ時に金額を四捨五入してはなりません。末尾のゼロを(盲目的に縮尺を変えるのとは違って)* pad *したい場合は、 'ROUND_HALF_UP'を使わずに行う必要があります。また、異なる通貨では、異なる数の末尾の小数が必要です。 –

+1

jro、スティーブのserialize()でwriteString()の代わりにwriteNumber()を使用すると、フィールドはJSONの数値として表示されます。 – caelumvox

16

SimpleModule module = new SimpleModule(); 
module.addSerializer(BigInteger.class, new ToStringSerializer()); 
objectMapper.registerModule(module); 

上記の例では、私は文字列に使用されますBigIntegersをシリアライズする(JavaScriptはこのような数値を処理できないため)。

+1

* *どこで*顧客シリアライザを定義しますか?これはまさに私がやりたいことですが、私はこのコードをどこに置くかを考え出すことはできません。 – DaveH

+0

あなたが好きな場所は、com.fasterxml.jackson.databind.JsonSerializerを実装するだけです。 – Modi

+0

少し具体的にできますか?私はまだそれを置く場所を取得していません。 – Wouter

4

私はjackson-datatype-moneyのメンテナーの一人です。私は確かに偏っているので、塩の粒でこの答えを取ってください。モジュールはあなたのニーズをカバーしなければならず、かなり軽量です(追加のランタイム依存性はありません)。さらに、それはJackson docsSpring docsに記載されており、すでにそれをジャクソンの公式エコシステムに統合する方法についてもsome discussionsさえありました。

関連する問題