How to format simple string?

Ok, I'm feeling like an idiot for asking this question, but I have hard time figuring it out by myself.
If I have string like this one:

String data = "{\"latitude\":\"123.34\",\"longitude\":\"245.89\",\"altitude\":\"401.23\",\"speed\":\"0\",\"deviceId\":\"867372057405818\"}";

but instead of hardcoded numbers inside the string I want to place variables. How to do that?

the real important question is what do you want to do with it.

if this is to print it out (SD, LCD, Web, Serial, ...) then just don't build it. Send the pieces separately

Serial.print(F("{\"latitude\":\"");
Serial.print(latitude, 6); 
Serial.print(F("\",\"longitude\":\"");
Serial.print(longitude, 6); 
...

you could also use a JSON library (but requires more memory)

Do not make things harder than they need to be ...

http://arduiniana.org/libraries/streaming/

It's actually a JSON indeed. I want to construct it and send it after that. Can you give me a link to proper library?

One that is frequently used is ArduinoJson

No library needed! Simple to format data from Arduino:

https://www.stm32duino.com/viewtopic.php?f=42&t=959&p=6305&hilit=nodered#p6305

You start like this:

Serial.print("{\"H2O_Tmp\":"); Serial.print(temp);  Serial.print (",");

And end like this:

 Serial.print("\"EGT_12\":"); Serial.print(temp);  Serial.print("}\n");

You did not say why you need to do that, so I will assume you have a good reason. Here's my solution:

char longStr[6], latStr[6], altStr[6], data[80];
dtostrf(longitude, 1, 2, longStr);
dtostrf(latitude, 1, 2, latStr);
dtostrf(altitude, 1, 2, altStr);
sprintf(data, "{\"latitude\":\"%s\",\"longitude\":\"%s\",\"altitude\":\"%s\",\"speed\":\"%d\",\"deviceId\":\"%ld\"}", longStr, latStr, altStr, speed, deviceId);

However you do it, avoid the String class. Use of the String class can lead to memory problems. See the evils of Strings.

sprintf is what you need

Better yet, snprintf().

1 Like

I guess it depends how you want to balance convenience versus memory impact

Strings could work to, at the risk of poking holes in the heap if not done the right way and extra memory requirements

sprintf() is costly in Flash memory compared to just using basic cString operations and dtostrf for example.
but this is less costly than ArduinoJson

         float curr_latitude = gps.location.lat();
         float curr_longitude = gps.location.lng();
         float curr_altitude = gps.altitude.meters();
         float curr_speed = gps.speed.kmph();

         String result;
         DynamicJsonDocument doc(1024);
         JsonObject obj = doc.as<JsonObject>();
         obj["latitude"] = curr_latitude;
         obj["longitude"] = curr_longitude;
         obj["altitude"] = curr_altitude;
         obj["speed"] = curr_speed;
         obj["deviceId"] = "867372057405818";
         serializeJson(doc, result);
         SerialMon.println(result); //returns null

Well if I try to serialize the data Arduino Json returns null....

try this

#include <ArduinoJson.h>

float curr_latitude = 48.85848453108126;
float curr_longitude = 2.2943126752811525;
float curr_altitude = 35;
float curr_speed = 0;

void setup() {
  Serial.begin(115200); Serial.println();

  String result;
  DynamicJsonDocument doc(200); // allocates in the heap
  doc["latitude"]   = curr_latitude;
  doc["longitude"]  = curr_longitude;
  doc["altitude"]   = curr_altitude;
  doc["speed"]      = curr_speed;
  doc["deviceId"]   = "867372057405818";
  serializeJson(doc, Serial);

  serializeJson(doc, result);
  Serial.print("\n\nThe String is: "); Serial.println(result);
}

void loop() {}

with Serial monitor open at 115200 bauds, you should see

{"latitude":48.85849,"longitude":2.294313,"altitude":35,"speed":0,"deviceId":"867372057405818"}

The String is: {"latitude":48.85849,"longitude":2.294313,"altitude":35,"speed":0,"deviceId":"867372057405818"}

1 Like

Actually did the job but caused more problems....the idea is that I am serializing some data from gps then I send it as Json to Api and this happens every 1 min. Now the first time I send it everything works ok after that nothing happens. It's like there is memory issue or something....

void loop() {
 while (Serial2.available() > 0){
    gps.encode(Serial2.read());
    if (gps.location.isUpdated()){ 
         float curr_latitude = gps.location.lat();
         float curr_longitude = gps.location.lng();
         float curr_altitude = gps.altitude.meters();
         float curr_speed = gps.speed.kmph();
         String result;
         DynamicJsonDocument doc(200);
         doc["latitude"]   = curr_latitude;
         doc["longitude"]  = curr_longitude;
         doc["altitude"]   = curr_altitude;
         doc["speed"]      = curr_speed;
         doc["deviceId"]   = "867372057405818";
         serializeJson(doc, result);
         delay(2000);
             
      // Making an HTTP POST request
       SerialMon.println("Performing HTTP POST request...");
      //Send the actual HTTP POST request to API
      client.print(String("POST ") + "http://something/api" + " HTTP/1.1\r\n");
      client.print(String("Host: ") + "http://something" + "\r\n");
      client.println("Connection: close");
      client.println("Content-Type: application/json");
      client.print("Content-Length: ");
      client.println(result.length());
      client.println();
      client.println(result);

      unsigned long timeout = millis();
      while (client.connected() && millis() - timeout < 10000L) {
        // Print available data (HTTP response from server)-have to be 201 Created
        while (client.available()) {
          char c = client.read();
          SerialMon.print(c);
          timeout = millis();
        }
      }
      SerialMon.println();
    }
  }

But yes your suggestion works fine!

just allocate the doc only once, not every time you get something

put this line

DynamicJsonDocument doc(200);

before the setup so that you have a global variable

200 was just a guess, you need to size it appropriately. (although should be OK)

there is an Assistant | ArduinoJson 6 on the web site of the author

but if you don't do more with JSON, I agree with the others, sprintf() is good enough :slight_smile:

1 Like

Actually although it's buggy the code works from time to time :smiley: :smiley: Problem is that I'm trying to combine 2 or 3 sources into one and there are most likely a lot of mistakes.... So I'll try to rewrite it tommorow and see what happens then and if I can solve it will ask for help in the forum again. Thanks for the help!