Search code examples
javajacksonjava-money

CurrencyUnit of javamoney can't be used as class of a field and deserialized by Jackson due InvalidDefinitionException


I have a pojo that has a field of type CurrencyUnit from the javamoney library. When I marshall this pojo Jackson throws an exception. I remember this exception when I did not define any default constructor. But in this case I can not maintain the CurrencyUnit class since it's coming from a dependency. How can I still make this work?

Exception:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `javax.money.CurrencyUnit` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information\n at 

Solution

  • You should write a custom serialiser/deserialiser for each type from javax.money package you want to use or register already created module. For example: jackson-datatype-money.

    You need to add dependency:

    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>jackson-datatype-money</artifactId>
        <version>1.3.0</version>
    </dependency>
    

    Simple example how to use:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import org.zalando.jackson.datatype.money.MoneyModule;
    
    import javax.money.CurrencyUnit;
    import javax.money.Monetary;
    
    public class JsonMoneyApp {
    
        public static void main(String[] args) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
            mapper.registerModule(new MoneyModule());
    
            CurrencyUnit cu = Monetary.getCurrency("USD");
            String json = mapper.writeValueAsString(cu);
            System.out.println(json);
    
            CurrencyUnit unit = mapper.readValue(json, CurrencyUnit.class);
            System.out.println(unit);
        }
    }
    

    above code prints:

    "USD"
    USD