¿ProtoStuff no es compatible con la serialización/deserialización de BigDecimal?

¡Trabajar juntos para crear y crecer juntos! Este es el día 12 de mi participación en el "Nuggets Daily New Plan·August Update Challenge", haz clic para ver los detalles del evento

Usualmente uso ProtoStuff como una herramienta de serialización para serializar algunos objetos POJO, pero en el uso real, se encuentra que hay problemas al serializar objetos BigDecimal

  • Independientemente del número, la matriz de bytes resultante es la misma
  • No se puede deserializar correctamente

Registre este problema a continuación

1. Reproducción de escena

Las dependencias protostuff que usamos son las siguientes

 <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>
复制代码

Escriba una demostración de prueba simple, de la siguiente manera

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);
}
复制代码

Ejecutar de la siguiente manera

2. Causas sospechosas y métodos compatibles

No encontré una razón específica, hay un problema en github: github.com/protostuff/… , donde la respuesta es

Protostuff funciona en tipos definidos por el usuario (pojos), no en tipos jdk incorporados.

La declaración anterior es que ProtoStuff es más para la serialización de objetos simples, no del tipo jdk básico, por lo que se recomienda serializar un objeto cuya variable miembro sea BigDecimal

A continuación, probemos, definamos un objeto simple con un miembro 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);
}
复制代码

La salida de prueba es la siguiente

Aunque lo anterior puede funcionar normalmente, es un poco diferente de lo que esperábamos.Para serializar un BigDecimal, es necesario definir un POJO para envolverlo, lo cual es un poco problemático; por lo que un método obsceno es realizar la serialización y deserialización para BigDeimal trato especial

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");
    }
}
复制代码

Prueba de nuevo, ejecución normal

declaración

No es tan bueno como una carta de fe. El contenido ya ha sido escrito y es puramente de la familia. Debido a la capacidad personal limitada, es inevitable que haya omisiones y errores. Si encuentra errores o tiene mejores sugerencias, puede criticarlas y corregirlas. Gracias.

  • QQ: Un gris gris / 3302797840
  • Número público: un blog gris
  • Un sitio gris: hhui.top

Supongo que te gusta

Origin juejin.im/post/7133583979667521544
Recomendado
Clasificación