4
  public class TestJacksonColor {
        public static void main(String [] args) throws IOException {
            ObjectMapper objectMapper = new ObjectMapper();
            Color black = new Color(0, 0, 0);
            String json = objectMapper.writeValueAsString(black);
            Color backToObject = objectMapper.readValue(json, Color.class);
        }
    }

The code attempts to take an java.awt.color class serialize it using jackson objectmapper. Take the resulting json string and deserialize it back to an java.awt.color class. However when doing the deserialization the following error occurs.

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class java.awt.Color]: can not instantiate from JSON object

1 Answers1

6

You'll need a custom serializer and deserializer. There are some pre-built modules around, but I'm unaware of one that handles java.awt.Color.

Here's an example that defines the serialiser/deserializer pair and registers a module to handle Color objects:

public class JacksonColorTest {

    public static class ColorSerializer extends JsonSerializer<Color> {
        @Override
        public void serialize(Color value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeStartObject();
            gen.writeFieldName("argb");
            gen.writeString(Integer.toHexString(value.getRGB()));
            gen.writeEndObject();
        }
    }

    public static class ColorDeserializer extends JsonDeserializer<Color> {
        @Override
        public Color deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            TreeNode root = p.getCodec().readTree(p);
            TextNode rgba = (TextNode) root.get("argb");
            return new Color(Integer.parseUnsignedInt(rgba.textValue(), 16), true);
        }
    }

    public static void main(String [] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(Color.class, new ColorSerializer());
        module.addDeserializer(Color.class, new ColorDeserializer());
        objectMapper.registerModule(module);

        Color testColor = new Color(1, 2, 3, 4);
        String json = objectMapper.writeValueAsString(testColor);
        Color backToObject = objectMapper.readValue(json, Color.class);

        if (!testColor.equals(backToObject)) {
            throw new AssertionError("round trip failed");
        }
    }
}
teppic
  • 7,051
  • 1
  • 29
  • 35
  • Thanks! My solution is similar to the one you made. I use many awt classes which seems to not be jackson compatible out of the box, but I just made custom de/serializers for all of them works like a charm. – Carl Henrik Klåvus Feb 09 '17 at 08:26