Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exclude field from class serialization in runtime?

How to exclude class field from serialization process in runtime ? There is transient modifier for compilation time but what about runtime ? I mean common java serialization with ObjectOutputStream, not gson or something.

Sorry I think I didn't explain right. This is not exactly about serialization , but about de-serialization. I have batch of legacy files and handle them like this:

public class Deserialize {  /**  * @param args  * @throws IOException   * @throws ClassNotFoundException   */ public static void main(String[] args) throws ClassNotFoundException, IOException {     File file = new File("/home/developer/workspace/DDFS/some.ddf");     HackedObjectInputStream in = new HackedObjectInputStream(new GZIPInputStream(new FileInputStream(file)));      System.out.println("Attempt to open " + file.getAbsolutePath());     Object obj = in.readObject();     in.close();   }   static class HackedObjectInputStream extends ObjectInputStream     {          /**          * Migration table. Holds old to new classes representation.          */         private static final Map<String, Class<?>> MIGRATION_MAP = new HashMap<String, Class<?>>();          static         {             MIGRATION_MAP.put("DBOBExit", Exit.class);         }          /**          * Constructor.          * @param stream input stream          * @throws IOException if io error          */         public HackedObjectInputStream(final InputStream stream) throws IOException         {             super(stream);         }          @Override         protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException         {             ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();              for (final String oldName : MIGRATION_MAP.keySet())             {                 if (resultClassDescriptor.getName().equals(oldName))                 {                     resultClassDescriptor = ObjectStreamClass.lookup(MIGRATION_MAP.get(oldName));                    }             }              return resultClassDescriptor;         }      } 

}

This code works fine for most of files , but some files throws

Exception in thread "main" java.lang.ClassCastException: cannot assign instance of java.awt.Polygon to field Exit.msgbackPt of type java.awt.Point in instance of Exit at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2053) 

because of different versions of Exit class . New version has new fields. Error disappearing when I add transient to new fields, but another files starts to throwing an exception (latest files).

So can I add transient to these new fileds in runtime if I detect legacy serilized file ? Maybe reflection or something ?

like image 816
gaponov Avatar asked Jan 29 '13 12:01

gaponov


People also ask

How would you exclude a field of a class from serialization?

If there are fields in Java objects that do not wish to be serialized, we can use the @JsonIgnore annotation in the Jackson library. The @JsonIgnore can be used at the field level, for ignoring fields during the serialization and deserialization.

How do you restrict class in serialization?

There is no direct way to prevent sub-class from serialization in java. One possible way by which a programmer can achieve this is by implementing the writeObject() and readObject() methods in the subclass and needs to throw NotSerializableException from these methods.

How do you avoid variables to serialize?

You can prevent member variables from being serialized by marking them with the NonSerialized attribute as follows. If possible, make an object that could contain security-sensitive data nonserializable. If the object must be serialized, apply the NonSerialized attribute to specific fields that store sensitive data.

How can you avoid certain member variables of class from getting serialized?

Question 7: How can you avoid certain member variable of class to be serialized? Answer: You can mark that variable as either static or transient.


1 Answers

The documentation of ObjectOutputStream says:

The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also.

So when you declare a variable as transient, it should be ignored by ObjectOutputStream. Make sure that you use the transient keyword and not a @Transient annotation. Such annotations are used by some ORM frameworks to mark fields which are not supposed to be saved in databases. They are meaningless for the buildin serialization framework.

private transient String foo; // Field gets ignored by ObjectOutputStream @Transient private String bar; // Treated normally by ObjectOutputStream (might mean something for some other framework) 
like image 148
Philipp Avatar answered Sep 28 '22 03:09

Philipp