Skip to content

Instantly share code, notes, and snippets.

@stickfigure
Last active June 4, 2021 22:36
Show Gist options
  • Save stickfigure/b4d2af290407f9af4cce to your computer and use it in GitHub Desktop.
Save stickfigure/b4d2af290407f9af4cce to your computer and use it in GitHub Desktop.
Jackson serializer and deserializer for Joda Money
package com.orbitkit.houston.util.json;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.example.MoneySerializer.MoneyJson;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import java.io.IOException;
import java.math.BigDecimal;
/**
* Will deserialize a Money that was serialized with the MoneySerializer. Also understands a simple decimal as USD.
*/
public class MoneyDeserializer extends StdDeserializer<Money> {
private static final long serialVersionUID = 2518470236548239933L;
/** */
public MoneyDeserializer() {
super(Money.class);
}
/** */
@Override
public Money deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
if (jp.getCurrentToken().isNumeric()) {
final BigDecimal amount = jp.getDecimalValue();
return Money.of(CurrencyUnit.USD, amount);
} else if (jp.getCurrentToken().isStructStart()) {
final MoneyJson json = jp.readValueAs(MoneyJson.class);
final CurrencyUnit currency = json.getCurrency() == null ? CurrencyUnit.USD : CurrencyUnit.of(json.getCurrency());
if (json.getCents() != null) {
return Money.ofMinor(currency, json.getCents());
}
if (json.getAmount() != null) {
return Money.of(currency, json.getAmount());
}
throw new IOException("Money structure needs either 'cents' or 'amount'");
} else {
throw new IOException("Expected either a number or a money structure");
}
}
}
package com.example;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.Data;
import org.joda.money.Money;
import java.io.IOException;
import java.math.BigDecimal;
/**
*/
public class MoneySerializer extends JsonSerializer<Money> {
@Data
static class MoneyJson {
private final Integer cents;
private final BigDecimal amount;
private final String symbol;
private final String currency;
private final String pretty;
}
@Override
public void serialize(final Money value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException {
final MoneyJson json = new MoneyJson(value.getAmountMinorInt(), value.getAmount(), value.getCurrencyUnit().getSymbol(), value.getCurrencyUnit().getCode(), prettyPrint(value));
jgen.writeObject(json);
}
private String prettyPrint(final Money money) {
final String text = money.getCurrencyUnit().getSymbol() + money.getAmount().toPlainString();
return text.endsWith(".00") ? text.substring(0, text.length() - 3) : text;
}
}
@mjaggard
Copy link

mjaggard commented Jul 6, 2015

I would rather have it fail than get USD back if the currency somehow ends up as null.

@stickfigure
Copy link
Author

Updated with what I'm using these days. My app is all USD, but if yours isn't, change behavior to whatever you would like!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment