2012-07-03 19 views
21

Obecnie używam Jackson'a do wysyłania wyników JSON z mojej aplikacji internetowej wiosennej.Serializacja Java na Jacksona JSON: Pola pieniężne

Problem, który mam, polega na uzyskaniu wszystkich pól pieniężnych do wydrukowania z 2 miejscami dziesiętnymi. Nie udało mi się rozwiązać tego problemu za pomocą metody setScale (2), ponieważ numery takie jak 25,50 są skracane do 25,5 itd.

Czy ktoś inny poradził sobie z tym problemem? Myślałem o zrobieniu klasy Money z niestandardowym serializatorem Jacksona ... czy możesz stworzyć niestandardowy serializator dla zmiennej pola? Prawdopodobnie możesz ... Ale nawet mimo wszystko, w jaki sposób mogę uzyskać numerację klientów, aby dodać numer jako liczbę z 2 miejscami dziesiętnymi?

+0

W jakich miejscach przechowujesz te wartości? "BigDecimal"? –

+0

@GregKopff yes a BigDecimal – ControlAltDel

Odpowiedz

5

Miałem ten sam problem i miałem to sformatowane w JSON jako ciąg zamiast. Może być trochę hack, ale jest łatwy do wdrożenia.

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

Możesz użyć niestandardowego serializera w swoim polu pieniężnym. Oto przykład z MoneyBean. Pole kwota zostanie przypisane z @JsonSerialize (przy użyciu = ...).

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

To wszystko. BigDecimal jest teraz wydrukowany we właściwy sposób. Użyłem prostej testówki, aby to pokazać:

@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

Przyjemne podejście, ale drukuje je jako ciąg znaków - nie jako typ liczbowy w wyjściu JSON. – jro

+17

Z punktu widzenia biznesu jest to okropne podejście. Pieniądze nie powinny być zaokrąglane w czasie serializacji. Jeśli chcesz * pad * z zerami końcowymi (różniącymi się od ślepego ustawiania skali), musisz to zrobić bez 'ROUND_HALF_UP'. Również różne waluty oczekują różnej liczby końcowych wartości dziesiętnych. –

+1

jro, Jeśli parametr writeNumber() zostanie użyty zamiast writeString() w seriali Steve'a(), to pole będzie wyświetlane jako liczba w JSON. – caelumvox

16

Zamiast ustawiania @JsonSerialize na każdego członka lub getter można skonfigurować moduł używania serializatora custome dla pewnego typu:

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

W powyższym przykładzie użyłem do łańcucha serializer do serializacji BigIntegers (ponieważ javascript nie może obsłużyć takich wartości liczbowych).

+1

* gdzie * mogę zdefiniować numerser klienta? To jest dokładnie to, co chcę zrobić, ale mogę; t opracować, gdzie umieścić ten kod. – DaveH

+0

Gdziekolwiek chcesz, musisz zaimplementować com.fasterxml.jackson.databind.JsonSerializer – Modi

+0

Czy możesz być nieco bardziej konkretny? Nadal nie wiem, gdzie to umieścić. – Wouter

4

Jestem jednym z opiekunów jackson-datatype-money, więc weź tę odpowiedź z przymrużeniem oka, ponieważ jestem zdecydowanie stronniczy. Moduł powinien pokrywać twoje potrzeby i jest dość lekki (brak dodatkowych zależności w czasie wykonywania). Ponadto jest wspomniany w Jackson docs, Spring docs i było nawet some discussions już o tym, jak zintegrować go z oficjalnym ekosystemem Jacksona.

Powiązane problemy