passare da JSON a MsgPack in modo compatibile all'indietro con Paho MQTT (JavaScript)

picockpit.com fa un uso pesante di MQTT. Per la prossima versione 2.0 ho deciso di passare a MsgPack.

Perché MsgPack?

MsgPack (in realtà chiamato MessagePack - i pacchetti tendono ad usare MsgPack) è un formato binario, volto alla compatibilità con JSON, ma diminuendo la dimensione del file (che è buono per risparmiare banda e risorse del server).

Un altro vantaggio: MessagePack permette di incorporare dati binari (ci sono alcuni casi d'uso interessanti previsti per PiCockpit v2.1+).

Rispetto ad altri formati di serializzazione binari (ad esempio BSON) MsgPack mira a una maggiore compatibilità con JSON, è più compatto, e può essere decodificato come un flusso!

Messaggi conservati dal passato

A causa dei messaggi conservati che sono ancora in JSON (e anche i client legacy che inviano ancora messaggi JSON), tuttavia, la compatibilità all'indietro deve essere fornita, specialmente sul lato JavaScript.

Non fornire la compatibilità all'indietro porterà ai seguenti problemi con Paho:

onConnectFailure;Connessione MQTT non riuscita (5): AMQJS0005E Errore interno. Messaggio di errore: AMQJS0009E Dati UTF malformati:ad -4f ., Stack trace: Nessuna pila di errori disponibile

onConnectFailure;Connessione MQTT non riuscita (5): AMQJS0005E Errore interno. Messaggio di errore: Trovati 231 byte extra nel buffer[1], Stack trace: No Error Stack Available

Codifica per il fallback a JSON

Paho non ci dà accesso ai dati del messaggio stesso che ha nelle sue strutture (vedere Codice Paho qui).

Quindi possiamo ripiegare sulla cattura delle eccezioni, assumendo che il messaggio sarà molto probabilmente nel formato MsgPack, e se la decodifica fallisce, passerà a JSON.

E se la decodifica di JSON fallisce, forniamo un fallback {} contro il fuzzing:

extractMessage(message){
     // 20.7.2020: passare a msgPack; deve essere payloadBytes, non payloadString
     var decodificatoMessaggio = {};
     prova {
         decodificatoMessaggio = decode(message.payloadBytes);
     }
     catch (e){
         console.log("decode error caught ");
         console.log(e);
         prova {
             decodificatoMessaggio = JSON.parse(message.payloadString);
         }
         catch (e){
             console.log("messaggio malformato (né JSON né MsgPack) - interpretato come oggetto vuoto {}");
         }
     }
     return decodedMessage;
     // return JSON.parse(message.payloadString);
}

immagine

  • si noti che usiamo payloadBytes per accedere al messaggio per msgPack, e payloadString per la decodifica JSON
  • notate che la decodifica (e la codifica) sono incluse in questo modo: import { encode, decode } da "@msgpack/msgpack"; nel mio flusso di lavoro Webpack

Riferimenti