ProtoStuff ne prend pas en charge la sérialisation/désérialisation BigDecimal ?

Travailler ensemble pour créer et grandir ensemble ! C'est le 12ème jour de ma participation au "Nuggets Daily New Plan · August Update Challenge", cliquez pour voir les détails de l'événement

J'utilise habituellement ProtoStuff comme outil de sérialisation pour sérialiser certains objets POJO, mais en utilisation réelle, on constate qu'il y a des problèmes lors de la sérialisation des objets BigDecimal

  • Quel que soit le nombre, le tableau d'octets résultant est le même
  • Impossible de désérialiser correctement

Enregistrez ce problème ci-dessous

1. Reproduction de scène

Les dépendances protostuff que nous utilisons sont les suivantes

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

Rédigez une démo de test simple, comme suit

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

Exécuter comme suit

2. Causes suspectées et méthodes compatibles

Je n'ai pas trouvé de raison précise, il y a un problème sur github : github.com/protostuff/… , où la réponse est

Protostuff fonctionne sur les types définis par l'utilisateur (pojos), pas sur les types jdk intégrés.

La déclaration ci-dessus est que ProtoStuff est plus pour la sérialisation d'objets simples, pas le type jdk de base, il est donc recommandé de sérialiser un objet dont la variable membre est BigDecimal

Ensuite, essayons, définissons un objet simple avec un membre 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 sortie du test est la suivante

Bien que ce qui précède puisse fonctionner normalement, c'est un peu différent de ce que nous espérions. Pour sérialiser un BigDecimal, il est nécessaire de définir un POJO pour l'envelopper, ce qui est un peu gênant ; donc une méthode obscène consiste à effectuer la sérialisation et la désérialisation pour traitement spécial BigDeimal.

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

Testez à nouveau, exécution normale

déclaration

Ce n'est pas aussi bon qu'une lettre de foi. Le contenu a déjà été écrit, et il est purement de la famille. En raison de capacités personnelles limitées, il est inévitable qu'il y ait des omissions et des erreurs. Si vous trouvez des bogues ou avez mieux suggestions, vous êtes invités à les critiquer et à les corriger. Merci

  • QQ : Un gris gris / 3302797840
  • Numéro public : un blog gris
  • Un site gris : hhui.top

Je suppose que tu aimes

Origine juejin.im/post/7133583979667521544
conseillé
Classement