Limiting decimal places in JSON object - Arduino_JSON library

Hi, I’m trying out the beta version of the Arduino_JSON library. It seems to be working ok, but I’ve noticed that it is introducing a lot of decimal places in the JSON objects.

When I run the code below, x, y and z, which start with 2 decimal places, are expanded to 8 plus within the object. This sort of behaviour will have performance implications in my application as I’m using JSON to define serial packets. I’d like them to be as small as possible.

Is there any way of limiting the number of decimal places that may be represented in the JSON object?

txMagPkt:
{“pi”:“ma”,“data”:[123.44999696,-234.559997568,345.67300416]}

#include <Arduino_JSON.h>
.
.
.
void MagPktDemo(){

  Serial.println("Magnetometer Packet Demo");
  Serial.println("========================\n");

  JSONVar txMagPkt;
  txMagPkt = JSONPacket("ma", "data", 123.45, -234.56, 345.67);

  Serial.println("txMagPkt:");
  Serial.println(txMagPkt);
  Serial.println("\nPacket Deconstruction");

  Serial.print("Packet Identifier = ");
  String pi;
  pi = txMagPkt["pi"];
  Serial.println(pi);
  
  double x, y, z;
  x = txMagPkt["data"][0];
  y = txMagPkt["data"][1];
  z = txMagPkt["data"][2];
  
  Serial.print("x = ");
  Serial.println(x);
  Serial.print("y = ");
  Serial.println(y);
  Serial.print("z = ");
  Serial.println(z);

}

JSONVar JSONPacket(String key, String tripletName, double v1, double v2, double v3){
  JSONVar result;

  result["pi"] = key;
  result[tripletName];
  result[tripletName][0] = v1;
  result[tripletName][1] = v2;
  result[tripletName][2] = v3;
  
  return result;
}

Hi Robert,

In your function, JSONPacket, you've defined those parameters as doubles (same as floats in Arduino C). By your very definition of those variables, they will take up 4 bytes of space regardless (and honestly, a lot of those numbers are probably junk- at best you get 6-7 digits of precision and that's total digits, not to the right of the decimal point).

If you REALLY wanted, you could try some hacky method, depending on the range of your expected values, by multiplying your double by 10 or 100 or whatever, then casting it to an unsigned int (uint_16) and converting it back later downstream. That would cut the size in half from 4 bytes to 2 bytes but that's still only 2 bytes saved in the first place. Doing math on floats is slower anyway so by the time you do the first mathematical scaling operation, cast, recast and descale, I don't think you're going to have saved anything.

Could you elaborate on the performance concern a little more?

Thanks for your reply. I'm new to the whole idea of using JSON objects as packets, but it was suggested by someone on this forum and I thought it had some merit.

My current understanding, which is totally up for grabs, is that a JSON packet would be transmitted over a serial link as ascii text, so any additional characters would impact on the overall link throughput. Not necessarily a problem in every situation, but it has the potential to be so if not easily overcome by some means.

If that understanding is incorrect and the JSON packet is sent in a binary form, then the four-byte representation for a float would be as small as it can get, regardless of how many characters are contained in string representation. But this doesn't sound particularly portable between different languages, which is why I have assumed that ascii representation is the common format.

I still have a way to go before getting my head completely around this topic and would welcome some clarity on the representation used for serialisation, but I like the hack you suggested. It would work for all of my currently envisaged applications and would provide optimal throughput whether ascii or binary.

Thanks again.

I assume you're using sandeep's Arduino_JSON?

I haven't used any of the Arduino JSON libraries, but after briefly looking at his source code, I believe you're making a JSON object which is still comprised of those primitives (i.e. doubles - see line 57: https://github.com/arduino-libraries/Arduino_JSON/blob/master/examples/JSONObject/JSONObject.ino). You can confirm this using the typeof method.

I think we need to step back a little. ASCII isn't a data type- it's an encoding method so they have nothing to do with the number of characters sent- that's determined by the data type of the variable being transmitted. It was only (relatively) recently that Serial.print could handle doubles. What's the bigger picture of this project? How are you transmitting this data?Are you going to just use Serial.print or are you going to use a different library and method?

I would recommend starting off slowly and making sure you get the fundamentals down first. Don't even worry about performance yet which probably isn't even the problem you think it is.