Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Serialization: shallow copying non-serializable fields?  (Read 708 times)
0 Members and 1 Guest are viewing this topic.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Posted 2012-08-05 18:51:51 »

I suspect this is really easy and I'm just being stupid, but is there a way to serialize an object so that some fields are serialized as references rather than being recursively serialised themselves?

As an example:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
class World // not serializable
{
  // whole bunch of world data
}

class Quest implements Serializable
{
  // some stuff that should be deep cloned when serialized
 private Goal goal;
  ...etc...

  // Reference to world, which should reference the same object when deserialized
 private World world;
}


Basically I'm (ab)using serialization to do deep copies on rather large graphs of objects. But some of the objects reference the game world which there is only one of and should reference the same world when cloned.

I could mark world as transient, but then I end up with a null reference after serialization. And I guess I could provide a custom readObject that would re-populate the 'world' field, but due to it's lack of scope I'd have to pull it out of a global somewhere, which is pretty hacky. If this was C I'd just write the address of the object into the stream and read it out and cast it to the right object type, but obviously that's not an option here.

Anyone any suggestions?

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Danny02
« Reply #1 - Posted 2012-08-05 19:07:10 »

why not clone your object correctly?
using serialisation is very hacky on it self, either you hack your hole programm or you just let it be.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #2 - Posted 2012-08-05 19:10:57 »

why not clone your object correctly?

If you know of a way of doing a deep clone on a complicated graph of objects via Object.clone() that's as elegant and robust as using serialization then I'm all ears.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online princec

JGO Kernel


Medals: 342
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #3 - Posted 2012-08-05 21:30:40 »

I'm doing exactly this for the savedgames in my SPGL based stuff. The savedgames graphs reference all the stuff in Resources but of course I don't actually want the stuff in Resources to get serialized otherwise when they get deserialized... well, you know.

Here's the trick, which you can adapt:

In AbstractResource:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
   /**
    * Serialization support. We completely replace the serialized feature with an
    * instance of SerializedFeature instead.
    */

    public final Object writeReplace() throws ObjectStreamException {
       if (Resources.isRunMode()) {
          // We're in "Run Mode"
         if (name == null) {
             // No name, so have to serialize directly.
            return this;
          } else {
             // Got a name, so send a SerializedFeature that just references this
            return new SerializedResource(this);
          }
       } else {
          // This is "compile time" so we serialize directly
         return this;
       }
    }


    private static final class SerializedResource implements Serializable {

       private static final long serialVersionUID = 1L;

       private String resourceName;
       private transient AbstractResource resource;

       public SerializedResource(AbstractResource resourceToSerialize) {
          resourceName = resourceToSerialize.getName();
       }

       /**
        * Provides a hashcode
        */

       @Override
   public int hashCode() {
      return resourceName.hashCode();
       }

       @Override
   public boolean equals(Object obj) {
          if (obj == null || !(obj instanceof SerializedResource)) {
             return false;
          }
          SerializedResource r = (SerializedResource) obj;
          if (obj == this) {
             return true;
          }
          if (r.resource != null && resource != null) {
             return r.resource.equals(resource);
          } else if (r.resourceName != null && resourceName != null) {
             return r.resourceName.equals(resourceName);
          } else {
             return false;
          }
       }

       /**
        * @returns a AbstractResource
        */

       private Object readResolve() throws ObjectStreamException {
          try {
             return Resources.get(resourceName);
          } catch (Exception e) {
             throw new InvalidObjectException("Failed to deserialize feature "+resourceName+" due to "+e);
          }
       }
    }


Cas Smiley

Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #4 - Posted 2012-08-06 07:09:40 »

why not clone your object correctly?

If you know of a way of doing a deep clone on a complicated graph of objects via Object.clone() that's as elegant and robust as using serialization then I'm all ears.
Since I love pimping my own stuff so much, Kryo to the rescue!!
https://code.google.com/p/kryo/#Copying/cloning

Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #5 - Posted 2012-08-06 08:55:42 »

Thanks guys. I ended up writing a ShallowHandle<T> class to deal with this for me:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
package crimgen;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ShallowHandle<T> implements Serializable
{
   private transient T target;
   
   public ShallowHandle()
   {
     
   }
   
   public ShallowHandle(T target)
   {
      this.target = target;
   }
   
   public void set(T t)
   {
      this.target = t;
   }
   
   public T get()
   {
      return target;
   }
   
   @Override
   @SuppressWarnings("rawtypes")
   public boolean equals(Object obj)
   {
      ShallowHandle other = (ShallowHandle)obj;
      return this.target.equals(other.target);
   }
   
   private void writeObject(ObjectOutputStream arg) throws IOException
   {
      ShallowCapableObjectOutputStream out = (ShallowCapableObjectOutputStream)arg;
      out.writeShallowObject(target);
   }
   
   @SuppressWarnings("unchecked")
   private void readObject(ObjectInputStream arg) throws IOException
   {
      ShallowCapableObjectInputStream in = (ShallowCapableObjectInputStream)arg;
      target = (T)in.readShallowObject();
   }
}


And having it save out a reference in a custom output/input stream that also has a map of id->shallow objects.

Nate: Kryo did actually spring to mind, but I'm just prototyping for now and I already had the deep copying done with serialization a while ago. I'll bear it in mind if/when I start making this thing properly.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (24 views)
2014-07-24 01:59:36

Riven (23 views)
2014-07-23 21:16:32

Riven (18 views)
2014-07-23 21:07:15

Riven (21 views)
2014-07-23 20:56:16

ctomni231 (50 views)
2014-07-18 06:55:21

Zero Volt (45 views)
2014-07-17 23:47:54

danieldean (36 views)
2014-07-17 23:41:23

MustardPeter (39 views)
2014-07-16 23:30:00

Cero (54 views)
2014-07-16 00:42:17

Riven (54 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!