Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegating creator fails to work for binary data (byte[]) with binary formats (CBOR, Smile) #1711

Closed
ghost opened this issue Jul 23, 2017 · 3 comments
Milestone

Comments

@ghost
Copy link

ghost commented Jul 23, 2017

Jackson Versions: 2.8.9, 2.9.0.pr4

This issue might belong to jackson-dataformats-binary.

I created a class which is basically a wrapper around a byte[], using @JsonValue and @JsonCreator.
This works fine using the default JsonFactory, however when using a SimleFactory or CBORFactory (and probably others) the deserialization fails: It returns a byte[] instead of the expected target class (which causes a ClassCastException in the calling code).

This problem only occurs with byte[]. Other types such as int[], String[] or byte[][] are fine.

public class TestByteArray {
    private static class ByteArray {
        private final byte[] val;

        @JsonCreator public ByteArray(byte[] val) { this.val = val;}

        @JsonValue public byte[] getValue() { return val;}
    }

    public static void main(String[] args) throws IOException {
        //This works fine
        test(new ObjectMapper(new JsonFactory()));
        //This throws java.lang.ClassCastException: [B cannot be cast to TestByteArray$ByteArray
        test(new ObjectMapper(new SmileFactory()));
        System.out.println("No exception thrown.");
    }

    private static void test(ObjectMapper mapper) throws IOException {
        byte[] bytes = {1, 2, 3, 4, 5};
        ByteArray read = mapper.readValue(mapper.writeValueAsBytes(new ByteArray(bytes)), ByteArray.class);
        if (!Arrays.equals(bytes, read.val))
            throw new IllegalStateException("Arrays not equal");
    }
}
@cowtowncoder
Copy link
Member

Thank you for reporting this. It could be either due to binary codecs, or databind not handling the case for some reason -- the way binary codecs expose binary content does differ from that of textual ones: whereas JSON parser has no way of knowing that a JSON String encodes byte[] (it must come from POJO type declaration), Smile/CBOR codecs do recognize it as binary and return JsonToken.VALUE_EMBEDDED_OBJECT. But why this prevents correct functioning of delegating creator is different story.

@cowtowncoder
Copy link
Member

Yes, I can reproduce this as shown.

@cowtowncoder cowtowncoder added this to the 2.9.0 milestone Jul 26, 2017
@cowtowncoder cowtowncoder changed the title OM.readValue returns byte[] on reading @JsonValue Wrapper class for byte[] array from a binary format Delegating creator fails to work for binary data (byte[]) with binary formats (CBOR, Smile) Jul 26, 2017
@cowtowncoder cowtowncoder modified the milestones: 2.9.0, 2.8.10 Jul 26, 2017
@cowtowncoder
Copy link
Member

Interesting. Turns out that delegating-creator case was not covered for JsonToken.VALUE_EMBEDDED_OBJECT; I added this, fix will be in 2.8.10 / 2.9.0.
I think I will also add an explicit check to give better exception message in other cases; ability to "coerce" native/embedded object into target type is a powerful feature, but it has to obey JVM type limitations... so in this case it'd be better to get a JsonMappingException, instead of relying on JVM giving opaque ClassCastException with no context.

cowtowncoder added a commit that referenced this issue Jul 26, 2017
…low handling via `DeserializationProblemHandler`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant