Parse Json download size

It almost works. I get the first 4 'sunrise/sunset'

Scratch that, I have increased the StaticJsonDocument filter to 500 and it works

In my current (working) sketch I can get each 'sunrise' separately with something along the lines of

filter["daily"] [0] [sunrise];
filter["daily"] [1] [sunrise];
filter["daily"] [3] [sunrise];
//etc
//etc

Can this be done in your example?

if you add this at the end of the setup()

  for (size_t i = 0; i < doc["daily"].size(); i++) {
    uint32_t t = doc["daily"][i]["sunrise"];
    Serial.print(i); Serial.write('\t'); Serial.println(t);
  }

you'll see

0	1642925007
1	1643011331
2	1643097652
3	1643183971
4	1643270287
5	1643356601
6	1643442913
7	1643529223

is this what you want ?

Almost perfect :grinning:
Can I extract just one day for example [5] ?

Never mind, I have found it with the following:

    uint32_t t = doc["daily"][5]["sunrise"];
 
        Serial.println(5); Serial.write('\t'); Serial.println(t);

:wink: yes it's just like going through an array (using the overloaded [] operator)

Thank you.

Now the big question is, How do I download the API and store it just as the data is stored in your json.h example?

I suppose it's just a GET request to the Open Weather API ?
where did you get the JSON from?

It is from OpenWeatherMap. My current sketch accesses the API every 5 minutes and parses out certain bits of data that I want but it only works on the smaller API as I stated in my opening question.

using filters you can avoid storing the full data and get into the memory issues you seemed to have

The first section is as follows:

void makehttpRequest() {
  epochTime = getTime();
  client.stop();
  if (client.connect(server, 80)) {
    Serial.println("HTTP connecting...");
    client.println("GET /data/2.5/onecall?lat=52.4976&lon=-2.1689&exclude=minutely,hourly,alerts&units=metric&appid=51ddde7c19ccef007569f7922c24887d");
    client.println("Host: api.openweathermap.org");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();
    Serial.println("Success ");
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 5000) {
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
      }
    }

    char c = 0;
    while (client.available()) {
      c = client.read();
      if (c == '{') {
        startJson = true;         // set startJson true to indicate json message has started
        jsonend++;
      }
      if (c == '}') {
        jsonend--;
        delay(10);
      }
      if (startJson == true) {
        text += c;
      }
      if (jsonend == 0 && startJson == true) {
        parseJson(text.c_str());  // parse c string text in parseJson function
        text = "";                // clear text string for the next time
        startJson = false;        // set startJson to false to indicate that a new message has not yet started

      }
    }
  }
  else {
    // if no connction was made:
    Serial.println("connection failed");
    return;
  }
}

And the second is this:

void parseJson(const char * jsonString) {

 DynamicJsonBuffer jsonBuffer(200);

  JsonObject& root = jsonBuffer.parseObject(jsonString);
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }

  long int api_call = root["current"]["dt"];
  int weather_id = root["current"]["weather"][0]["id"];
  String weather_description = root["current"]["weather"][0]["description"];
  float moon_phase = root["daily"][0]["moon_phase"];
  long int sunrise = root["current"]["sunrise"];
  long int sunset = root["current"]["sunset"];
  float c_temp = root ["current"]["temp"];
  float c_humi = root["current"]["humidity"];
  float c_dp = root["current"]["dew_point"];
  float wind_speed = root["current"]["wind_speed"];
  int wind_deg = root["current"]["wind_deg"];
  day_1 = root["daily"][1]["weather"][0]["description"].asString();
  day_2 = root["daily"][2]["weather"][0]["description"].asString();
  day_3 = root["daily"][3]["weather"][0]["description"].asString();
  day_4 = root["daily"][4]["weather"][0]["description"].asString();
  day_5 = root["daily"][5]["weather"][0]["description"].asString();
  hourly_1 = root["daily"][4]["weather"][0]["description"].asString();// find parse

  Serial.print("Weather Description: ");
  Serial.println(weather_description);
  Serial.print("Weather id ");
  Serial.println(weather_id);
  Serial.print("Moon Phase ");
  Serial.println(moon_phase);
  Serial.print("Sunrise ");
  Serial.println(sunrise);
  Serial.print("Sunset ");
  Serial.println(sunset);
  Serial.print("Current Temperature ");
  Serial.println(c_temp);
  Serial.print("Current Humidity ");
  Serial.println(c_humi);
  Serial.print("Current Dewpoint ");
  Serial.println(c_dp);
  Serial.print("Indoor Temperature ");
  Serial.println(temp);
  Serial.print("Indoor Humidity ");
  Serial.println(humi);
  Serial.print("wind speed ");
  Serial.println(wind_speed);
  Serial.print("wind deg ");
  Serial.println(wind_deg);
  Serial.print("day 1 ");
  Serial.println(day_1);
  Serial.print("day 2 ");
  Serial.println(day_2);
  Serial.print("day 3 ");
  Serial.println(day_3);
  Serial.print("day 4 ");
  Serial.println(day_4);
  Serial.print("day 5 ");
  Serial.println(day_5);
  Serial.print("API call    ");
  Serial.println(api_call);
  Serial.print("Epoch Time: ");
  Serial.println(epochTime);
}

This is with ArduinoJson.h v5

That sound exactly what I need. So I assume it would download the entire API but ignore the bits I don't want and store the bits I do?

see

I see that this is how your example works but I don't see where I would put the 'download' of the API

Rather than having your sketch read characters from 'client' one at a time into a String named 'text' and then passing 'text' to deserializeJson(), just pass 'client' to deserializeJson() and let the library do the reading.

deserializeJson(doc, client, DeserializationOption::Filter(filter));

It will filter the JSON as it reads and will only store the parts the filter selects.

something like this possibly (typed here, untested)

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "XXXX";
const char* password = "XXXX";

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

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");   Serial.println(WiFi.localIP());

  WiFiClient client;  // or WiFiClientSecure for HTTPS
  HTTPClient http;
  DynamicJsonDocument doc(200);
  StaticJsonDocument<64> filter;

  filter["time"] = true;
  filter["data"] = true;

  // Send request
  http.begin(client, "http://arduinojson.org/example.json");
  int httpResponseCode = http.GET();
  if (httpResponseCode > 0) {
    deserializeJson(doc, client, DeserializationOption::Filter(filter));
    serializeJsonPretty(doc, Serial);
  } else {
    Serial.print("http get request returned : "); Serial.println(httpResponseCode);
  }

  http.end();
}

void loop() {}

Thank you so much. This works a treat :grinning:

I can now remove a LOT of code that is no longer required.

I have just tried it with the larger API and I can pick out all of the 'sunsets' as per your example.

Note that "sunset" does not depend on the weather. If you have the Latitude and Longitude of interest and date of interest you can calculate sunset directly on the Arduino.

Good news !

+1 on the ability to calculate sunset and other element form position and date