ProtoStuff doesn't support BigDecimal serialization/deserialization?

Work together to create and grow together! This is the 12th day of my participation in the "Nuggets Daily New Plan·August Update Challenge", click to view the event details

I usually use ProtoStuff as a serialization tool to serialize some POJO objects, but in actual use, it is found that there are problems when serializing BigDecimal objects

  • Regardless of the number, the resulting byte array is the same
  • Can't deserialize properly

Record this issue below

1. Scene reproduction

The protostuff dependencies we use are as follows

 <dependency>
    <groupId>com.dyuproject.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.1.3</version>
</dependency>
<dependency>
    <groupId>com.dyuproject.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.1.3</version>
</dependency>
复制代码

Write a simple test demo, as follows

public static byte[] serialize(Object obj) {
    Schema schema = RuntimeSchema.getSchema(obj.getClass());
    LinkedBuffer buffer = LinkedBuffer.allocate(1048576);

    byte[] protoStuff;
    try {
        protoStuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
    } catch (Exception var8) {
        throw new RuntimeException("Failed to serializer");
    } finally {
        buffer.clear();
    }

    return protoStuff;
}

public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
    if (paramArrayOfByte != null && paramArrayOfByte.length != 0) {
        Schema<T> schema = RuntimeSchema.getSchema(targetClass);
        T instance = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
        return instance;
    } else {
        throw new RuntimeException("Failed to deserialize");
    }
}


@Test
public void testSer() {
    byte[] ans = serialize(new BigDecimal(20));
    byte[] ans2 = serialize(new BigDecimal(120));

    System.out.println(new String(ans));
    System.out.println(new String(ans2));

    BigDecimal res = deserialize(ans, BigDecimal.class);
    System.out.println(res);
}
复制代码

Execute as follows

2. Suspected causes and compatible methods

I didn't find a specific reason, there is an issure on github: github.com/protostuff/… , where the reply is

Protostuff works on user-defined types (pojos), not on built-in jdk types.

The above statement is that ProtoStuff is more for the serialization of simple objects, not the basic jdk type, so it is recommended to serialize an object whose member variable is BigDecimal

Next, let's try it out, define a simple object with a member of BigDecimal

@Data
public static class InnerDecimal {
    private BigDecimal decimal;

    public InnerDecimal() {
    }

    public InnerDecimal(BigDecimal decimal) {
        this.decimal = decimal;
    }
}

@Test
public void testSer() {
    byte[] ans = serialize(new InnerDecimal(new BigDecimal(20.123)));
    byte[] ans2 = serialize(new InnerDecimal(new BigDecimal(120.1970824)));

    System.out.println(new String(ans));
    System.out.println(new String(ans2));

    InnerDecimal res = deserialize(ans, InnerDecimal.class);
    System.out.println(res);
}
复制代码

The test output is as follows

Although the above can work normally, it is a little different from what we hoped. To serialize a BigDecimal, it is necessary to define a POJO to wrap it, which is a bit troublesome; so an obscene method is to perform serialization and deserialization for BigDeimal. special treatment

public static byte[] serialize(Object obj) {
    if (obj instanceof BigDecimal) {
        obj = ((BigDecimal) obj).toPlainString();
    }

    Schema schema = RuntimeSchema.getSchema(obj.getClass());
    LinkedBuffer buffer = LinkedBuffer.allocate(1048576);

    byte[] protoStuff;
    try {
        protoStuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
    } catch (Exception var8) {
        throw new RuntimeException("Failed to serializer");
    } finally {
        buffer.clear();
    }

    return protoStuff;
}

public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
    if (paramArrayOfByte != null && paramArrayOfByte.length != 0) {
        Schema schema;
        if (targetClass.isAssignableFrom(BigDecimal.class)) {
            schema = RuntimeSchema.getSchema(String.class);
            Object instance = schema.newMessage();
            ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
            return (T) new BigDecimal((String) instance);
        } else {
            schema = RuntimeSchema.getSchema(targetClass);
            Object instance = schema.newMessage();
            ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
            return (T) instance;
        }
    } else {
        throw new RuntimeException("Failed to deserialize");
    }
}
复制代码

Test again, normal execution

statement

It is not as good as a letter of faith. The content has already been written, and it is purely from the family. Due to limited personal ability, it is inevitable that there will be omissions and mistakes. If you find bugs or have better suggestions, you are welcome to criticize and correct them. Thank you

  • QQ: A gray gray / 3302797840
  • Public number: a gray blog
  • A gray site: hhui.top

Guess you like

Origin juejin.im/post/7133583979667521544