Are there any good alternatives for serializing enums in Java?

The Java language has greatly benefited from adding enumerations to it; but, unfortunately, they do not work well when sending serialized objects between systems with different levels of code.

Example: suppose you have two systems A and B. Both of them start at the same code levels, but at some point they begin to see code updates at different points in time. Now suppose that there is some

public enum Whatever { FIRST; } 

And there are other objects that contain references to the constants of this enumeration. These objects are serialized and sent from A to B or vice versa. Now consider that B has a newer version of Whatever

 public enum Whatever { FIRST; SECOND } 

Then:

 class SomethingElse implements Serializable { ... private final Whatever theWhatever; SomethingElse(Whatever theWhatever) { this.theWhatever = theWhatever; .. 

gets an instance ...

 SomethingElse somethin = new SomethingElse(Whatever.SECOND) 

and then serialized and sent to A (for example, as a result of some RMI call). This is bad, because now there will be an error during deserialization on A: A knows any enum class, but in a version that does not have SECOND.

We found this a difficult way; and now I really want to use enumerations for situations that are actually "perfect for enumerations"; simply because I know that I cannot easily extend an existing enumeration later.

Now I'm wondering: are there any (good) strategies to avoid such enumeration compatibility issues? Or do I really need to go back to the "pre-enum" time; and not use enumerations, but should rely on a solution where I use simple strings everywhere?

Update: note that using serialversionuid does not help at all. This thing only helps you make incompatible changes “more obvious”. But the fact is, I don't care why deserialization fails - because I have to avoid it. And I am also not able to change the way we serialize our objects. We do RMI; and we serialize for binary; I have no way to change this.

+8
java enums serialization
source share
2 answers

Going back and forth on various solutions, I decided on the basis of a proposal from @GuiSim: you can build a class containing the enumeration value. This class may

  • perform individual deserialization; in this way, I can prevent that there will be no exceptions during the deserialization process.
  • provide simple methods, such as isValid () and getEnumValue (): the first tells you whether the deserialization of the enumeration is completed; and the second returns a deserialized enumeration (or throws an exception)
0
source share

As @Jesper mentioned in the comments, I would recommend something like JSON for your interservice communication. This will allow you more control over how unknown Enum values ​​are handled.

For example, using the always awesome Jackson , you can use the READ_UNKNOWN_ENUM_VALUES_AS_NULL or READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE deserialization functions . Both will allow your application logic to process unknown enum values ​​as you see fit.

Example (straight from Jackson's doc)

 enum MyEnum { A, B, @JsonEnumDefaultValue UNKNOWN } ... final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); MyEnum value = mapper.readValue("\"foo\"", MyEnum.class); assertSame(MyEnum.UNKNOWN, value); 
+6
source share

All Articles