How do correctly use Jackson Mixin annotation to instantiate a third party class?

穿精又带淫゛_ 提交于 2019-12-11 03:07:00

问题


I have a third party library class (from Apache Axis) that I want to serialize by Jackson JSON:

public class NonNegativeInteger extends BigInteger {

    public NonNegativeInteger(byte[] val) {
        super(val);
        checkValidity();
    } // ctor

    public NonNegativeInteger(int signum, byte[] magnitude) {
        super(signum, magnitude);
        checkValidity();
    } // ctor

    public NonNegativeInteger(int bitLength, int certainty, Random rnd) {
        super(bitLength, certainty, rnd);
        checkValidity();
    } // ctor

    public NonNegativeInteger(int numBits, Random rnd) {
        super(numBits, rnd);
        checkValidity();
    } // ctor

    public NonNegativeInteger(String val) {
        super(val);
        checkValidity();
    }

    public NonNegativeInteger(String val, int radix) {
        super(val, radix);
        checkValidity();
    } // ctor

    /**
     * validate the value against the xsd definition
     */
    private BigInteger zero = new BigInteger("0");
    private void checkValidity() {
        if (compareTo(zero) < 0) {
            throw new NumberFormatException(
                    Messages.getMessage("badNonNegInt00")
                    + ":  " + this);
        }
    } // checkValidity

    /**
     * Work-around for http://developer.java.sun.com/developer/bugParade/bugs/4378370.html
     * @return BigIntegerRep
     * @throws ObjectStreamException
     */ 
    public Object writeReplace() throws ObjectStreamException {
        return new BigIntegerRep(toByteArray());
    }

    protected static class BigIntegerRep implements java.io.Serializable {
        private byte[] array;
        protected BigIntegerRep(byte[] array) {
            this.array = array;
        }
        protected Object readResolve() throws java.io.ObjectStreamException {
            return new NonNegativeInteger(array);
        }
    }
}

I have my entity class containing a NonNegativeInteger field that I want to serialize by JSON:

public class TestEntity {

    private NonNegativeInteger number;

    public NonNegativeInteger getNumber() {
        return number;
    }

    public void setNumber(NonNegativeInteger number) {
        this.number = number;
    }
}

When I serialize the above object by Jackson JSON, I got the following error:

Can not instantiate value of type [simple type, class org.apache.axis.types.NonNegativeInteger] from Integral number; no single-int-arg constructor/factory method

Then I looked at the POST request entity, it is actually {"number" : 10} as serialized by Jackson. But since NonNegativeInteger doesn't have a constructor taking a single-int, Jackson can't instantiate a NonNegativeInteger object. So I followed someone's suggestions to add a Mixin class for NonNegativeInteger so that it will have a constructor with int as arg:

public abstract class NonNegativeIntegerMixin extends NonNegativeInteger {

    @JsonCreator
    public NonNegativeIntegerMixin(int val) {
        super(String.valueOf(val));
    }
}

Then I registered it in my JSON configuration class:

 objectMapper.addMixInAnnotations(NonNegativeInteger.class, NonNegativeIntegerMixin.class);

But it doesn't help, it still reported the same error. I tried manually writing the JSON request body to be {"number": "10"} then it worked well. But my client side used Jackson to serialize NonNegativeInteger. Jackson automatically converts to {"number": 10} without quotes. How can I fix this error?

Edit:

The NonNegativeInteger class doesn't have any class field (except a constant zero field). The number key is from my TestEntity class. So I even if I add @JsonProperty annotation in my NonNegativeIntegerMixin mixin class, Jackson JSON will not instantiate a NonNegativeInteger with an int type arg. Therefore, I still got the same error.


回答1:


Your mix-in annotation seems correct to me. So this could be a bug; so maybe file bug at:

https://github.com/FasterXML/jackson-databind/issues/

One possible reason for problems is that class is extending BigInteger, which has existing deserializer. This could result in annotations being ignored, wrt how instances are deserialized.



来源:https://stackoverflow.com/questions/28857897/how-do-correctly-use-jackson-mixin-annotation-to-instantiate-a-third-party-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!