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.

JsonMappingException not Serializable due to 2.7 reference to underlying parser

See original GitHub issue

JsonMappingExceptions thrown by the Jackson parser cannot be serialized. This breaks any code that assumes the exception (per the Serializable interface it implements) is serializable.

Since the exception contains a reference to a non-serializable parser (such as com.fasterxml.jackson.core.json.ReaderBasedJsonParser), serialization will throw a NotSerializableException. Furthermore, the parser may contain a reference to the class being parsed; if that class is not itself serializable, that too will prevent serialization.

The expected behavior would be that these exceptions would be serializable.

I ran across this issue when testing some code with a missing subtype. The following code will replicate this issue: import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.ByteArrayOutputStream;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;

public class SerializationTest {
    public static void main(String[] args) throws Exception {
        try {
            new ObjectMapper().readValue("{\"type\": \"B\"}", ClassToRead.class);
        } catch (JsonMappingException e) {
            try (ObjectOutputStream stream = new ObjectOutputStream(new ByteArrayOutputStream())) {
                stream.writeObject(e);
            } catch (NotSerializableException e2) {
                // java.io.NotSerializableException: com.fasterxml.jackson.core.json.ReaderBasedJsonParser
                System.err.println("Unable to serialize exception " + e);
                e2.printStackTrace();
            }
        }
        try {
            new ObjectMapper().readValue("{\"classToRead\": {\"type\": \"B\"}}", ContainerClassToRead.class);
        } catch (JsonMappingException e) {
            try (ObjectOutputStream stream = new ObjectOutputStream(new ByteArrayOutputStream())) {
                stream.writeObject(e);
            } catch (NotSerializableException e2) {
                // java.io.NotSerializableException: jackson.ContainerClassToRead
                System.err.println("Unable to serialize exception " + e);
                e2.printStackTrace();
            }
        }
    }
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property="type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = SubclassToRead.class, name = "A")
})
abstract class ClassToRead {}
class SubclassToRead extends ClassToRead {}

class ContainerClassToRead {
    public ClassToRead classToRead;
}

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Apr 19, 2016

Yes final fields must be set from within constructor, but what I meant was that I thought whoever constructed instances was not always in position to pass in all the information; and that this was why there were setters (setIndex() etc). I use final fields and immutable objects wherever possible otherwise, so I must have had some reason not to do that here. Another possible reason may have been that instances would be Jackson serializable/deserializable, not just JDK serializable (which in a way is secondary concern).

But looking at call chains it does not actually look like anything was actually calling setters so there does not seem current need to do that. I’ll clean this up for 2.8; for 2.7 I will leave things mostly as are just to keep even low likelihood problems at bay.

0reactions
mjustincommented, Apr 19, 2016

Thanks for the explanation; I haven’t had to work much with implementing serialization behavior, so I was wondering if that was intentional or not.

Six of one, half dozen of the other, I suspect; but it occurs to me that if you made the _from field transient, you could just initialize the _asString property and let the serialization do its thing with the same object. I don’t think it buys you anything, though:

Object writeReplace() {
    toString(); // Force creation of _asString if it has not been initialized yet
    return this;
}

As to the mutability thing, as long as the final fields are not initialized inline, you should be able to set them in the constructor. In fact, it wouldn’t compile unless the constructor was setting all the final fields.

Read more comments on GitHub >

github_iconTop Results From Across the Web

JsonMappingException not Serializable due to 2.7 reference ...
JsonMappingExceptions thrown by the Jackson parser cannot be serialized. This breaks any code that assumes the exception (per the ...
Read more >
JsonMappingException (jackson-databind 2.12.1 API)
Method that can be called to either create a new JsonMappingException (if underlying exception is not a JsonMappingException), or augment given exception with ......
Read more >
Serialization with Jackson - Documentation - Akka
In this documentation we have used MySerializable to make it clear that the marker interface itself is not provided by Akka. That is...
Read more >
serialize/deserialize java 8 java.time with Jackson JSON mapper
How do I use Jackson JSON mapper with Java 8 LocalDateTime? org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [ ...
Read more >
com.fasterxml.jackson.databind.JsonMappingException ...
JsonMappingException maven / gradle build tool code. ... mostly to * allow JDK serialization to work in case where {@link #_from} is *...
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