2012-07-03 16 views
21

Şu anda Spring tabanlı web uygulamamdan JSON sonuçları göndermek için Jackson kullanıyorum.Java'dan Jackson'a JSON serileştirme: Para alanları

Yaşadığım sorun, tüm para alanlarını 2 ondalık basamakla çıktı almaya çalışmak. Bu problemi, 25.50 gibi 25.5 vs

'a kesildiği için setScale (2) kullanarak çözemedim. Bu sorunla ilgilenen başka biri var mı? Özel bir Jackson serileştiricisi ile bir Para sınıfı yapmayı düşünüyordum ... bir alan değişkeni için özel bir seri hale getirici yapabilir misin? Muhtemelen ... Ama yine de, müşteri serileştiricisini sayıyı 2 ondalık basamaklı bir sayı olarak eklemek için nasıl alabilirim?

+0

Bu değerleri ne şekilde saklıyorsunuz? Bir BigDecimal? –

+0

@GregKopff yes a BigDecimal – ControlAltDel

cevap

5

Aynı sorunu yaşadım ve bunun yerine bir String olarak JSON olarak biçimlendirdim. Biraz kesmek olabilir ama uygulamak kolaydır. Bunun yerine her üyesinde @JsonSerialize ayarı veya belirli bir tür için bir custome serileştirici kullanılmalıdır bir modül yapılandırabilirsiniz getter ait

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

Para alanınızda özel bir seri hale getirici kullanabilirsiniz. İşte MoneyBean ile bir örnek. no'lu alan @ JsonSerialize (= ...) kullanarak açıklamalıdır.

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()); 
    } 
} 

Bu kadar. Bir BigDecimal şimdi doğru şekilde basılmıştır. Bunu göstermek için basit bir test çantası kullandım:

@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

Güzel bir yaklaşım, ancak bir dize olarak yazdırır - JSON çıktısında sayısal bir tür değil. – jro

+17

İş perspektifinden, bu korkunç bir yaklaşım. Para serileştirme zamanında yuvarlanmamalıdır. Sıfırdan (sıfırdan körü körüne ayarlamaktan farklı) * pad * ile * yapmak isterseniz, bunu ROUND_HALF_UP' olmadan yapmanız gerekir. Ayrıca, farklı para birimleri farklı sayıdaki izleyen ondalık sayıları bekler. –

+1

jro, Steve'in serialize() işlevinde writeString() yerine writeNumber() kullanılırsa, alan JSON'da bir sayı olarak gösterilecektir. – caelumvox

16

:

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

Yukarıdaki örnekte, ipi için kullanılan BigIntegers serileştirmek için serializer (javascript böyle sayısal değerleri işlemez).

+1

* Burada müşteri seri hale getiricisini tanımlayabilir miyim? Tam olarak yapmak istediğim şey bu, ama bu kodu nereye koyacağımı bilmiyorum. – DaveH

+0

İstediğiniz yerde, sadece com.fasterxml.jackson.databind.JsonSerializer – Modi

+0

'u uygulamak zorundasınız Biraz daha spesifik olabilir misiniz? Hala nereye koyacağımı anlamıyorum. – Wouter

4

jackson-datatype-money'un geliştiricilerinden biriyim, bu yüzden kesinlikle yanlı olduğumdan beri bu cevabı tuzla alın. Modül ihtiyaçlarınızı karşılamalı ve oldukça hafiftir (ek çalışma zamanı bağımlılıkları yoktur). Buna ek olarak, Jackson docs, Spring docs'da da belirtilmiştir ve zaten Jackson'ın resmi ekosistemine nasıl entegre edileceği konusunda bile some discussions vardı.

İlgili konular