Serialization of an object type enum contained in a serializable class

420 views Asked by At

I am trying to serialize an object type enum declared in my serializable class. I have already red all topics here but I did not find an answer to my issue. I hope someone can help me here. I actually am trying to serialize 2 objects type SType and CbitSet but I get the follow result:

<rSIt>
  <sType>S_V_INC</sType>
  <bits/>
  <mHave>true</mHave>
</rSIt>

I am expecting something like:

<rSIt>
  <sType>
     <code>VI</code>
     <description>V Inc</description>
     <name>S_V_INC</name>
  </sType>
  <bits>
    <words>{long[7]@5285}</words>
    <wordsInUse>7</wordsInUse>
    <sizeIsSticky>false</sizeIsSticky>
  <bits>
  <mHave>true</mHave>
</rSIt>

Here is my code:

    @XmlRootElement(name="rSIt")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class RSIt implements Serializable{
        private static final long serialVersionUID = -5848959699974019999L;
        @XmlElement
        private SType sType;
        @XmlElement
        private CbitSet bits = new CbitSet();
        @XmlElement
        private boolean mHave = true;

        public SType getSType() {
            return this.sType;
        }
        public void setSType(SType sType) {
            this.sType = sType;
        }
        public CbitSet getBits() {
            return this.bits;
        }

        public boolean ismHave() {
            return this.mHave;
        }
        public void setmHave(boolean mHave) {
            this.mHave = mHave;
        }

        public RSIt() {
            super();
        }

        public RSIt(SType sType, boolean mHave) {
            super();
            this.sType = sType;
            this.mHave = mHave;
        }

        public RSIt(SType sType, boolean mHave, Integer bit) {
            super();
            this.sType = sType;
            this.mHave = mHave;
            this.bits.set(bit);
        }
        }
    This is the implementation of SType  class (it is an Enum class):
    public enum SType {
        S_V_INC ("VI", "V Inc"),
        S_V_EXC ("VE", "V Exc"),
        S_RP_INC ("RI", "RP Inc"),
        S_RP_EXC ("RE", "RP Exc"),
        S_V_AN_F ("VA", "V F All");

        private final String code;
        private final String description;
        SearchType (String code, String description) {
            this.code = code;
            this.description = description;
        }
        public String getCode() {
            return code;
        }
        public String getDescription() {
            return description;
        }
    }
    This is the implementation of CbitSet class
    import java.util.BitSet;
    @XmlRootElement(name="rSIt")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class CbitSet extends BitSet implements Serializable{
        private static final long serialVersionUID = 476550000000055127L;

        private static final long longOne = 1;
        private static final long long64 = 64;

        public CbitSet() {
            super();
        }

        public long[] toLongArray() {
            long[] longs = new long[this.size() / 64];
            for (int i = 0; i < longs.length; i++)
                for (int j = 0; j < 64; j++)
                    if (this.get(i * 64 + j))
                        longs[i] |= longOne << j;
            return longs;
        }

        public void fromLongArray(long[] longs) {
            for (int i=0; i<longs.length*64; i++) {
                if ((longs[i/64]&(longOne<<(i%long64))) != 0) {
                    this.set(i);
                }
            }
        }

        public String toBitString() {
            StringBuilder sb = new StringBuilder();
            for (int x = 0; x < this.size(); x++) {
                if (this.get(x)) {
                    sb.append("1");
                } else {
                    sb.append("0");
                }
            }
            return sb.toString();       
        }

        public void fromBitString(String string) {
            int pos = 0;
            for (byte chr : string.getBytes()) {
                if ('1' == chr) {
                    this.set(pos);
                }
                pos++;
            }
        }
        public void set(List<Integer> bits) {
            set(bits,true);
        }
        public void set(List<Integer> bits, boolean value) {
            if (bits != null) {
                for (Integer bit : bits) {
                    if (bit != null) {
                        this.set(bit.intValue(), value);
                    }
                }
            }
        }
        public void set(Integer bitIndex) {
            if (bitIndex != null) {
                super.set(bitIndex);
            }
        }
        public void set(Integer bitIndex, boolean value) {
            if (bitIndex != null) {
                super.set(bitIndex, value);
            }
        }   
    }

    Thank you for your help guys.
1

There are 1 answers

12
leeyuiwah On

I am also learning ... and I tend to agree with the answer from another SO question (here) that

Enums in Java are meant to be immutable objects, in which case there is no point in serializing any of their fields.

However, if, for any reason, that you insist to get the marshalled result as you have specified, I found that I could do that by changing SType from an enum to a class, and then embedding another enum called EnumSType in it.

The code looks like this:

package SerializationQuestion1;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement(name="sType")
@XmlAccessorType(XmlAccessType.FIELD)   
public class SType {
    public enum EnumSType {
        S_V_INC ("VI", "V Inc"),
        S_V_EXC ("VE", "V Exc"),
        S_RP_INC ("RI", "RP Inc"),
        S_RP_EXC ("RE", "RP Exc"),
        S_V_AN_F ("VA", "V F All");

        @XmlElement
        private final String code;
        @XmlElement
        private final String description;
        EnumSType (String code, String description) {   // Bug fix 1
            this.code = code;
            this.description = description;
        }
        public String getCode() {
            return code;
        }
        public String getDescription() {
            return description;
        }
    }

    @XmlTransient
    private EnumSType sType;

    public EnumSType getsType() {
        return sType;
    }

    public void setsType(EnumSType sType) {
        this.sType = sType;
    }

    public SType () {};

    public SType (EnumSType sType) {
        this.sType = sType;
    }

    @XmlElement
    public String getCode() { return this.sType.getCode();};

    @XmlElement
    public String getDescription() { return this.sType.getDescription();};

    @XmlElement
    public String getName() { return this.sType.name();};
}

To instantiate an RSIt object, the code looks like this now:

RSIt rsit = new RSIt(new SType(EnumSType.S_V_INC), true, null);

The following was my marshalled output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rSIt>
    <sType>
        <code>VI</code>
        <description>V Inc</description>
        <name>S_V_INC</name>
    </sType>
    <bits/>
    <mHave>true</mHave>
</rSIt>