1

I want to integrate vavr validation library in my command dto's in a way that when command dto is deserialized from request, return type of the static factory will be Try but jackson is throwing following error :

Type definition error: [simple type, class com.foo.command.FooCommand]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.foo.command.FooCommand (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

Here is FooCommand

@AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class FooCommand {
    private String foo;
    private String bar;

    @JsonCreator
    public static Try<FooCommand> of(
            @JsonProperty("foo") String foo,
            @JsonProperty("bar") String bar
    ) {
        return Try.of(() -> {
            //Validate values
        });
    }
}

I am using spring 5 and it's annotated to deserialize request body automatically into controller parameter. Is something like this possible ? Thanks in advance.

  • What does FooCommand looks like? The class in your question is `RegisterConfiguration` but the return value is `Try`. – PolygonParrot Dec 24 '18 at 22:18
  • I have corrected class name in example to FooCommand. Thanks for pointing it out. –  Dec 24 '18 at 22:25
  • I think you should create a constructor and put `@JsonCreator` on top of the constructor – Mohsen Dec 24 '18 at 22:27
  • How is then FooCommand::of() method going to be called? –  Dec 24 '18 at 22:30
  • @SilvioMarijic `I am using spring 5 and it's annotated to deserialize request body automatically` I guess Spring calls it. – PolygonParrot Dec 24 '18 at 22:39
  • 1
    It seems like Jackson only uses factory methods if they have the same return type even if they got the `@JsonCreator` Annotation. – PolygonParrot Dec 24 '18 at 23:13
  • Yeah, that is wierd, I have no clue why that restriction on the return type. Everything works fine when I just return instance of FooCommand without wrapping it in a Try –  Dec 25 '18 at 00:37

1 Answers1

0

I had a similar problem that I fixed by using Converters: Using Jackson, how can I deserialize values using static factory methods that return wrappers with a generic type?

I haven't yet found how to apply the converters automatically, so you have to annotate every occurrence of the wrapped type in your requests.

public class Request {
    @JsonDeserialize(converter = FooCommandConverter.class)
    Try<FooCommand> command;
}

You can write a Converter like so:

public class FooCommandConverter
        extends StdConverter<FooCommandConverter.DTO, Try<FooCommand>> {

    @Override
    public Try<FooCommand> convert(FooCommandConverter.DTO dto) {
        return FooCommand.of(
            dto.foo,
            dto.bar
        );
    }

    public static class DTO {
        public String foo;
        public String bar;
    }
}
neXus
  • 2,005
  • 3
  • 29
  • 53