0

I have a byte array:

[11, 10, 17, 05, 00, 0a, 01, 02]

and a class:

class abc{

    short var1;              // [11, 10]
    int var2;                // [17, 05, 00, 0a]
    byte var3;               // [01]
    byte var4;               // [02]

}

In python there is a lib ctypes where you can provide a byte array and it will encode it to a object of a class (definitely structure needs to be defined before hand).

I am looking something similar in java, basically what I am looking for a method which can encode and decode byte array.

[11, 10, 17, 05, 00, 0a, 01, 02] => (some method) => object abc: abc.getVar3() // value of var3 needs to be 1 as per above structure.

also object abc => (some method) => [11, 10, 17, 05, 00, 0a, 01, 02].

Only solution I can think of is lots of if else statement is there any better way to do it.

I have checked this answer it serialises entire class as byte object but I only want to encode data, basically inject data in object and also retrieve data from object in byte array.

2
  • I would recommend using Jackson and serialize it into JSON. If you want a custom encoding as you mentioned then you will most probably need to get your hands dirty. The encoding that you specified is not backward compatible and is bound to break when things change. Commented Feb 1, 2021 at 9:43
  • ObjectInputStream, ObjectOutputStream? Commented Feb 1, 2021 at 9:45

3 Answers 3

1

DataInputStream allows you to read primitives from an input stream. Look out for following methods:

  • readShort()
  • readInt()
  • readByte()

Example code:

byte[] data = {0x11, 0x10, 0x17, 0x05, 0x00, 0x0a, 0x01, 0x02};

try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(data))) {
    abc value = new abc();
    value.var1 = in.readShort();
    value.var2 = in.readInt();
    value.var3 = in.readByte();
    value.var4 = in.readByte();
}
Sign up to request clarification or add additional context in comments.

3 Comments

This is similar solution what I am having right now I am slicing the array and creating desired data type and then inject that value in object, I have stored slice index and data type and to which variable to map it to in object in a map, but what I am looking for is that since I have already defined the class with its appropriate data types why can't I use that and inject values directly in that object similar to memmove method from python.
@ooo That's not possible because the memory layout of an object in Java is left to the implementor's discretion. Therefore, you don't know whether var1 comes before or after var2; instead, you have to assign them individually.
@k314159 is there any efficient way to do that, assuming you know before hand the class structure and when you get this byte array you can inject value in that. Also the ability to create the object and convert that to same byte array and send it. (Note that I am not talking to create byte array of entire class only of data in object)
0

There's several ways to do that. Here's a simple one:

byte[] values = [11, 10, 17, 05, 00, 0a, 01, 02]; //WARNING: update 0a to the right value in java

The class definition (class name start with uppercase in java):

class Abc{

    short[] var1;              // [11, 10]
    int[] var2;                // [17, 05, 00, 0a]
    byte var3;               // [01]
    byte var4;               // [02]
    
    public Abc(byte[] values){
      var1 = new short[]{(short)values[0],(short)values[1]};
      var2 = new int[]{(int)values[2],(int)values[3],(int)values[4],(int)values[5]};
      var3 = values[6];
      var4 = values[7];

    }
    
    public byte[] getBytes(){
      return new byte[]{ (byte)var1[0], (byte)var1[1], (byte)var2[0],(byte)var2[1], (byte)var2[2], (byte)var2[3], var3, var4};
    }

}

So to create a new object (objects are lowercase):

Abc abc = new Abc(values);
byte[] result = abc.getBytes();

2 Comments

there are more than unique 50 classes and I have just added 4 variable for example, I am looking for something general and lazy.
Please update your question since this comment is very relevant
0

Assuming you have looked at Serialization Utils from Apache Commons, you could understand that there should be some sort of class based object to be an input for any serialization algorithm.

However you want to avoid having a separate dedicated class to store and retrieve data (if I'm wrong clarify me). One possible workaround is to use a built-in class in java to encapsulate the data for you.

For example you could put your data fields in a List (ArrayList) or even better a Map (HashMap). Then you could serialize the map object so that it can be passed around. The good thing is these classes are already built into java so you don't need to create a separate class just for the sake of serialization.

Here is a sample example code:

import org.apache.commons.lang3.SerializationUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

class Abc {

    short var1;              // [11, 10]
    int var2;                // [17, 05, 00, 0a]
    byte var3;               // [01]
    byte var4;               // [02]

    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("var1", var1);
        map.put("var2", var2);
        map.put("var3", var3);
        map.put("var4", var4);

        return map;
    }

    public byte[] serializeMap() {
        return SerializationUtils.serialize((Serializable) toMap());
    }

    public Map<String, Object> deSerializeMap(byte[] serializedObject) {
        return SerializationUtils.deserialize(serializedObject);
    }

    public void setParams(Map<String, Object> deSerializedObject) {
        this.var1 = (short) deSerializedObject.get("var1");
        this.var2 = (int) deSerializedObject.get("var2");
        this.var3 = (byte) deSerializedObject.get("var3");
        this.var4 = (byte) deSerializedObject.get("var4");
    }
}

public class Test2 {
    public static void main(String[] args) {

        Abc obj = new Abc();
        obj.var1 = 10000;
        obj.var2 = 500000;
        obj.var3 = 2;
        obj.var4 = 30;

        Abc newObj = new Abc();
        newObj.setParams(newObj.deSerializeMap(obj.serializeMap()));

        System.out.printf("var1: %s\nvar2: %s\nvar3: %s\nvar4: %s\n", newObj.var1, newObj.var2, newObj.var3, newObj.var4);
    }
}

As you can see here, I use obj to create the values, then serialize it and newObj to deserialize and assign back to the variable.

obj could be belong to one class and you could serialize and send the values through network and can deserialize them on another object. This is possible because the HashMap is already built into Java.

Good thing here is that you don't need to have same class in both places. As long as both classes have above variables (variables don't even have to have a same name either, as long as type matches, this will work), you could implement this solution.

2 Comments

Is the same thing possible only by using java core lib?
@ooo it is perfectly possible. You already looked at those answers you mentioned. There are already many answers which only uses built in core modules. Just create another method which utilizes one of those answers and you can come up with your own way of serialization and deserialization without any third party modules

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.