Java naar Jackson JSON Serialisatie: Geldvelden

Momenteel gebruik ik Jackson om JSON-resultaten uit mijn opspring op basis van websoorten te verzenden.

Het probleem dat ik heb geprobeerd om alle geldvelden te krijgen om met 2 decimalen te worden uitgevoerd. Ik kon dit probleem niet oplossen met setScale(2), omdat cijfers zoals 25.50 zijn afgekapt tot 25.5 enz.

Heeft iemand anders dit probleem behandeld? Ik dacht erover om een ​​geldklasse te maken met een Custom Jackson Serializer … kun je een aangepaste serializer maken voor een veldvariabele? Je kunt waarschijnlijk … maar zelfs nog steeds, hoe kan ik mijn klant serializer krijgen om het nummer toe te voegen als een nummer met 2 decimalen?


Antwoord 1, Autoriteit 100%

U kunt een aangepaste serializer gebruiken op uw geldveld. Hier is een voorbeeld met een geldbean. Het veld bedrag wordt geannoteerd met @JSONSIERIZE (met = …) .

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

Dat is het. Een bigdecimal is nu op de juiste manier afgedrukt. Ik heb een eenvoudige testcase gebruikt om het te laten zien:

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

Antwoord 2, Autoriteit 51%

U kunt @JsonFormatannotatie gebruiken met shapeals STRINGop uw BigDecimalvariabelen. Hieronder verwijzen:

import com.fasterxml.jackson.annotation.JsonFormat;
  class YourObjectClass {
      @JsonFormat(shape=JsonFormat.Shape.STRING)
      private BigDecimal yourVariable;
 }

Antwoord 3, Autoriteit 43%

In plaats van het instellen van de @JSONSERIALIZE op elk lid of Getter, kunt u een module configureren die een custome serializer gebruikt voor een bepaald type:

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

In het bovenstaande voorbeeld gebruikte ik de to String Serializer om Bigintegers te serialiseren (omdat Javascript dergelijke numerieke waarden niet aankan).


Antwoord 4, Autoriteit 18%

Ik ben een van de onderhouders van jackson-datatype-geld , dus neem Dit antwoord met een korrel zout, want ik ben zeker bevooroordeeld. De module moet betrekking hebben op uw behoeften en het is behoorlijk lichtgewicht (geen extra runtime-afhankelijkheden). Daarnaast wordt het vermeld in de jackson docs , Spring Docs en er waren zelfs Sommige discussies al over hoe het te integreren in het officiële ecosysteem van Jackson.


Antwoord 5, Autoriteit 6%

Ik had hetzelfde probleem en ik had het in plaats daarvan in JSON geformatteerd. Kan een beetje een hack zijn, maar het is gemakkelijk te implementeren.

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

Antwoord 6, autoriteit 2%

Zoals Sahil Chhabrasuggereerde dat je @JsonFormatmet de juiste shapeop uw variabele.
Als je het wilt toepassen op elk BigDecimal-veld dat je in je Dto'shebt, kun je de standaardnotatie voor een bepaalde klasse overschrijven.

@Configuration
public class JacksonObjectMapperConfiguration {
    @Autowired
    public void customize(ObjectMapper objectMapper) {
         objectMapper
            .configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
    }
}

Antwoord 7

Geïnspireerd door Steve, en als de updates voor Java 11. Dit is hoe we de BigDecimal-heropmaak hebben gedaan om wetenschappelijke notatie te vermijden .

public class PriceSerializer extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        // Using writNumber and removing toString make sure the output is number but not String.
        jgen.writeNumber(value.setScale(2, RoundingMode.HALF_UP));
    }
}

Other episodes