1

I want to use @ConstructorProperties instead of @JsonCreator but it looks like it doesn't work in some scenarios.

@ConstructorProperties in jackson2 does not work when deserializing from array elements. Is there any way for both method1() and method2() to work with @ConstructorProperties?

I'm using jackson 2.13. Java 11.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.beans.ConstructorProperties;
import java.util.HashSet;
import java.util.Set;

class Scratch {
    public static void main(String[] args) throws JsonProcessingException {
        // THIS WORKS WHEN I USE @ConstructorProperties("value") ON CompId()
        method1();

        // THIS ONLY WORKS WHEN I USE @JsonCreator ON CompId()
        method2();
    }

    private static void method2() throws JsonProcessingException {
        Set<Long> compIds = new HashSet<>(1);
        compIds.add(123L);

        Dto1 dto1 = new Dto1(compIds);

        ObjectMapper objectMapper = new ObjectMapper();

        String str = objectMapper.writeValueAsString(dto1);

        Dto2 dto = objectMapper.readValue(str, Dto2.class);
        System.out.println(dto);
    }

    private static void method1() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        CompId compId1 = new CompId(123L);

        String str = objectMapper.writeValueAsString(compId1);

        CompId compId = objectMapper.readValue(str, CompId.class);
        System.out.println(compId);
    }


    public static class Dto1 {
        private final Set<Long> compIds;

        @ConstructorProperties("compIds")
        public Dto1(Set<Long> compIds) {
            this.compIds = compIds;
        }

        public Set<Long> getCompIds() {
            return compIds;
        }

        @Override
        public String toString() {
            return "Dto1{" +
                    "compIds=" + compIds +
                    '}';
        }
    }

    public static class Dto2 {
        private final Set<CompId> compIds;

        @ConstructorProperties("compIds")
        public Dto2(Set<CompId> compIds) {
            this.compIds = compIds;
        }

        public Set<CompId> getCompIds() {
            return compIds;
        }

        @Override
        public String toString() {
            return "Dto2{" +
                    "compIds=" + compIds +
                    '}';
        }
    }

    static class CompId {
        private long value;

        //@JsonCreator
        @ConstructorProperties("value")
        public CompId(long value) {
            this.value = value;
        }

        public long getValue() {
            return value;
        }



        @Override
        public String toString() {
            return "CompId{" +
                    "value=" + value +
                    '}';
        }
    }

}

This is the stacktrace I get:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `Scratch$CompId` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (123)
 at [Source: (String)"{"compIds":[123]}"; line: 1, column: 13] (through reference chain: Scratch$Dto2["compIds"]->java.util.HashSet[0])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1728)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1353)
kurt26
  • 21
  • 5

0 Answers0