question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Issue registering custom string deserializer via custom module

See original GitHub issue

I have a custom string deserializer that only accepts string tokens.

public class Deserializers extends com.fasterxml.jackson.databind.deser.Deserializers.Base {
    @Override
    public @Nullable JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription description) throws JsonMappingException {
        if (type.hasRawClass(String.class)) {
            new StringDeserializer();
        }

        return null;
    }

    public static class StringDeserializer extends JsonDeserializer<String> {
        @Override
        public String deserialize(JsonParser parser, DeserializationContext context) throws IOException {
            System.out.println("StringDeserializer!");

            if (!parser.hasToken(JsonToken.VALUE_STRING)) {
                throw context.wrongTokenException(parser, String.class, JsonToken.VALUE_STRING, "");
            }

            return parser.getText();
        }
    }
}

When I register the custom deserializer in an ObjectMapper via SimpleModule it gets called.

try {
    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(String.class, new Deserializers.StringDeserializer());
    objectMapper.registerModule(module);
    objectMapper.readValue("{ \"string\": true }", Foo.class);
} catch (Exception exception) {
    System.out.println(exception);
}
public class Foo {
    public String string;
}

Results in

StringDeserializer!
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_TRUE), expected VALUE_STRING:
 at [Source: (String)"{ "string": true }"; line: 1, column: 13] (through reference chain: com.booking.demandapi.system.Initializer$Foo["string"])

as expected. However, if I register the custom deserializer with a custom Module

try {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new Module());
    objectMapper.readValue("{ \"string\": true }", Foo.class);
} catch (Exception exception) {
    System.out.println(exception);
}
public class Module extends com.fasterxml.jackson.databind.Module {
    @Override
    public String getModuleName() {
        return getClass().getName();
    }

    @Override
    public void setupModule(com.fasterxml.jackson.databind.Module.SetupContext context) {
        context.addDeserializers(new Deserializers());
    }

    @Override
    public Version version() {
        return Version.unknownVersion();
    }
}

the custom deserializer is not being run. Is this the right way of registering it?

I have other custom serializers and deserializers registered in a similar way (findEnumDeserializer and findSerializer) and they are working.

I have considered using SimpleModule instead of a custom Module but I have generic Enum serializers and haven’t been able to register them via addSerializer with type = Enum.class since they are JsonSerializer<Enum<?>>.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
joca-btcommented, Dec 11, 2019

That’s embarrassing, I’ll go hide in a cave and never leave. Our static analysis is supposed to flag these things.

1reaction
cowtowncodercommented, Dec 11, 2019

Oh. But before that, looking at original code, is this actually what you have?

        if (type.hasRawClass(String.class)) {
            new StringDeserializer();
        }

… because it is not actually returning the deserializer… 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Getting Started with Custom Deserialization in Jackson
This quick tutorial will illustrate how to use Jackson 2 to deserialize JSON using a custom Deserializer.
Read more >
type handling of custom serializer and deserializer
Register a custom serializer and deserializer for Interface I. Serialize using: String json = ObjectMapper mapper.writerWithType(C.class).
Read more >
How do I call the default deserializer from a custom ...
As StaxMan already suggested you can do this by writing a BeanDeserializerModifier and registering it via SimpleModule .
Read more >
A custom module for Jackson object mapper using Java ...
How can we customize the way the Jackson ObjectMapper serialize/deserialize Money instances? We can write a custom Module for it. By defining a ......
Read more >
Creating custom serializer and deserializer classes - IBM
Create a custom class that extends a Jackson StdSerializer or JsonDeserializer class. Note: When you register a serializer or deserializer class for a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found