ArduinoJson help with char array

Hello,

I'm using ArduinoJson to help parse the char array I create after sending a GET request for my hue lighting system.

Assume that the GET request is sent and the correct info is returned.

This is the sequence:

  • I send a get request to the bridge (hue lighting system), and it returns the json info. (this works)
  • I filter through them, storing only the section of the response that I want in json[].(this works).
  • I check the array by printing out all the chars from json[].(this works)
  • I use ArduinoJson to parse the char array. (not working as intended)
  • For some reason that I can't figure out, it doesn't work using json[] which is my intention.
  • but when I use json2[], it works. json2[] is a copy+paste of the serial monitor results in #3.

is there something wrong in the way that I am storing or handling json[] that treats it differently from json2[]?

I get no compiler errors, just "parseObject() failed"

note: i'm just looking for help with this parsing issue and why one works and the other does despite what seems like the same data. I'd appreciate the focus staying there and not on my likely-unorthodox or poor coding :slight_smile:

Best,

//This is where the get request was just sent.

    while(client.connected())
    {
       
        while(client.available() && endBrace == false)
        {
           
            char c = client.read();


                  
                   
                  if(readingJson == true)
                  {
                        if (c == '\"' ) // if quotes, add a slash then quotes
                        {
                          
                          json[index] = '\\'; // insert slash 
                          index++;
                          json[index] = c; // Store it
                          index++;
                          
                        }
                        else if(c == '\}') // if end bracket, add bracket and then quotes and break loop
                        {
                          json[index] = c; // Store it
                          index++;
                          json[index] = '\"';
                          index++;
                          endBrace = true;
                       
                          
                        }
                        else// if no special characters, add to array
                        {
                          json[index] = c; // Store it
                          index++;
                        }
                  }
                 
                  if(c == '\{' && countBrace == 1) // second bracket, add quotes
                  {
                    
                      json[index] = '\"';
                      index++;
                      json[index] = c; // Store it
                      index++;
                      readingJson = true;
                      countBrace == 2;

                  }
                  
                  if(c == '\{' && countBrace == 0) // first brace detected, skipped
                  {
                      
                      countBrace = 1;
                  }
    

        }

     }

//checking index. this works.

   Serial.println(" ");
   Serial.println("index is ");
   Serial.println(index);
   Serial.println(" ");
   

// checking char stored. this works
   
   Serial.println(" ");
   Serial.println("json READ ");
   Serial.println(" ");


   for (int i = 0; i < index; i++)
   {
     Serial.print(json[i]);
   }
   
   Serial.println(" ");

// json2 is a fixed replica of the results printed from json[] above.  

//char json2[] = "{\"on\":true,\"bri\":207,\"hue\":13234,\"sat\":208,\"effect\":\"none\",\"xy\":[0.5090,0.4149],\"ct\":459,\"alert\":\"none\",\"colormode\":\"xy\",\"reachable\":true}";
   
// Arduino Json
 
   StaticJsonBuffer<200> jsonBuffer;
   JsonObject& root = jsonBuffer.parseObject(json); // works with json2, not with json

  if (!root.success()) 
  {
    Serial.println("parseObject() failed");
    return;
  }


  int bri = root["bri"];  // works with json2, not with json
  int hue = root["hue"];  // works with json2, not with json
  int sat = root["sat"];  // works with json2, not with json

  Serial.println(bri); // works with json2, not with json
  Serial.println(hue); // works with json2, not with json
  Serial.println(sat); // works with json2, not with json

Your code doesn't compile.

http://snippets-r-us.com/

If you want to dictate exactly how help is to be provided I suggest you pay someone. Otherwise abide by forum rules. Post all your code.

There are occasions when you can't see the wood for the trees. (missing a single = where it should be a == maybe) BUT, if you've been looking at a piece of code long enough and still can't find the problem. It's probable that the problem is somewhere that you HAVEN'T been looking.

When you give us a snippet, you are forcing us to use the same blinkers that have impeded your progress.

Thanks, I can do it later today though unless you're in my house i'll have to use another url to get the Json.

KenF:
There are occasions when you can't see the wood for the trees. (missing a single = where it should be a == maybe) BUT, if you've been looking at a piece of code long enough and still can't find the problem. It's probable that the problem is somewhere that you HAVEN'T been looking.

When you give us a snippet, you are forcing us to use the same blinkers that have impeded your progress.

I took KenF's advice and looked again with fresh eyes, and eventually figured it out. ArduinoJson lists this link for the json to use

char json[] =
"{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}";

I was modifying the get results to match that format, but when I sequentially printed out those chars it didn't actually have the \ characters which I had added from the url response.

I removed the escapes from my original storage into the array and now it works.

Thanks KenF

  • Karma

I may be having a similiar issue with trying to assemble a json array from data received from the weatherunderground site. www.wunderground.com

Below is the data that the site sends back in response to my GET command to my arduino with a wifi module called esptoy from Introducing the ESP8266 WiFi Toy (ESPToy) « RAYSHOBBY.NET)

The full source code I used as a basis for my sketch can be found here: ESP8266 Weather Display

my GET command

cmd = "GET /api/";
    cmd += YOURKEY;
    cmd += "/conditions/q/";
    cmd += LOCATIONID;
    cmd +=".json";
    cmd += " HTTP/1.1\r\nHost: api.wunderground.com\r\n\r\n";

websites json reply:

{ "response": { 
  "version": "0.1", 
  "termsofService": "http://www.wunderground.com/weather/api/d/terms.html", 
  "features": { 
  "conditions": 1 
  } 
  }, 
  "current_observation": { 
   "image": { 
    "url": "http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png", 
    "title": "Weather Underground", 
    "link": "http://www.wunderground.com" 
    }, 
    "display_location": { 
    "full": "San Francisco, CA", 
    "city": "San Francisco", 
    "state": "CA", 
    "state_name": "California", 
    "country": "US", 
    "country_iso3166": "US", 
    "zip": "94101", 
    "latitude": "37.77500916", 
    "longitude": "-122.41825867", 
    "elevation": "47.00000000" 
    }, 
    "observation_location": { 
    "full": "SOMA - Near Van Ness, San Francisco, California", 
    "city": "SOMA - Near Van Ness, San Francisco", 
    "state": "California", 
    "country": "US", 
    "country_iso3166": "US", 
    "latitude": "37.773285", 
    "longitude": "-122.417725", 
    "elevation": "49 ft" 
    }, 
    "estimated": {}, 
    "station_id": "KCASANFR58", 
    "observation_time": "Last Updated on June 27, 5:27 PM PDT", 
    "observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700", 
    "observation_epoch": "1340843233", 
    "local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700", 
    "local_epoch": "1340843234", 
    "local_tz_short": "PDT", 
    "local_tz_long": "America/Los_Angeles", 
    "local_tz_offset": "-0700", 
    "weather": "Partly Cloudy", 
    "temperature_string": "66.3 F (19.1 C)", 
    "temp_f": 66.3, 
    "temp_c": 19.1, 
    "relative_humidity": "65%", 
    "wind_string": "From the NNW at 22.0 MPH Gusting to 28.0 MPH", 
    "wind_dir": "NNW", 
    "wind_degrees": 346, 
    "wind_mph": 22.0, 
    "wind_gust_mph": "28.0", 
    "wind_kph": 35.4, 
    "wind_gust_kph": "45.1", 
    "pressure_mb": "1013", 
    "pressure_in": "29.93", 
    "pressure_trend": "+", 
    "dewpoint_string": "54 F (12 C)", 
    "dewpoint_f": 54, 
    "dewpoint_c": 12, 
    "heat_index_string": "NA", 
    "heat_index_f": "NA", 
    "heat_index_c": "NA", 
    "windchill_string": "NA", 
    "windchill_f": "NA", 
    "windchill_c": "NA", 
    "feelslike_string": "66.3 F (19.1 C)", 
    "feelslike_f": "66.3", 
    "feelslike_c": "19.1", 
    "visibility_mi": "10.0", 
    "visibility_km": "16.1", 
    "solarradiation": "", 
    "UV": "5", 
    "precip_1hr_string": "0.00 in ( 0 mm)", 
    "precip_1hr_in": "0.00", 
    "precip_1hr_metric": " 0", 
    "precip_today_string": "0.00 in (0 mm)", 
    "precip_today_in": "0.00", 
    "precip_today_metric": "0", 
    "icon": "partlycloudy", 
    "icon_url": "http://icons-ak.wxug.com/i/c/k/partlycloudy.gif", 
    "forecast_url": "http://www.wunderground.com/US/CA/San_Francisco.html", 
    "history_url": "http://www.wunderground.com/history/airport/KCASANFR58/2012/6/27/DailyHistory.html", 
    "ob_url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=37.773285,-122.417725" 
    } 
  }

I am using the ArduinoJson lib ver 4
and looking to pull certain elements out of the full json response like these:

char* conds[]={"\"city\":","\"local_time_rfc822\":","\"weather\":","\"temp_f\":","\"relative_humidity\":","\"wind_dir\":","\"wind_mph\":","\"pressure_in\":"};
int num_elements = 8;  // number of conditions you are retrieving, count of elements in conds

I use the following code (see getWeatherData_jsonData) to read from the serial port assigned to the wifi module to build a local json array that contains just the data elements I am interested in:

The problem is if the json data sent back contains embedded commas within a data element then my parser stops at the embedded comma when it should ignore it and look for the commas that separate the data elements, like in a csv file. This cause the function parseJSON to hang.

Can anyone suggest a method to skip over the embedded commas like in data elements: observation_time and local_time_rfc822

example data elements with embeded comma: aka June 17, 5:27 and Wed, 27

     "observation_time": "Last Updated on June 27, 5:27 PM PDT", 
    "observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700", 
    "observation_epoch": "1340843233", 
    "local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700",

extract just certain data elements:

boolean getWeatherData_jsonData()
{
  unsigned int ii = 0; //timeout counter
  char json[jsonbuffer_size]="{"; // array for Json parsing
  int nn = 1;          // character counter for json
  
  for (int jj=0;jj<num_elements;jj++)
  {
    // this works because it finds the first occurrence of the 'condition' as defined in the cond array' 
    // so it returns city, state, full, etc from the 'display_location part of the json data
    while (!esp.find(conds[jj])) {
    } // find just the data elements we are interested in // do nothing unless something matches, this needs a timeout or failed to find anything test
  
    String Str1 = conds[jj];
  
    for (int kk=0; kk<(Str1.length());kk++)
    {
      json[nn] = Str1[kk];
      nn++;
    }
    while (ii<60000) 
    {
      if(esp.available()) 
      {
        char c = esp.read();
  
        if(c==',') break;
        json[nn]=c;
        nn++;
        ii=0;
      }
      ii++;
    }
    if (jj==num_elements-1)
    {
      json[nn]=close_brace;
    }
    else
    {
      json[nn]=comma;
    }
    nn++;
  }
  dbg.print(F("\nRaw json data: "));
  dbg.println(json);                 // uncomment to see the json data
  
  if (!parseJSON(json))              // parse and show on debug monitor the weather data for the location  
  {
    return false;
  }
  return true;
}  


boolean parseJSON(char json[300])          // for some reason the compiler.linker/preprocessor will not accept a define for buffer size
{
  StaticJsonBuffer<300> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(json);

  if (!root.success())
  {
    dbg.println("parseObject() failed");
    return false;
  }

  //const char* city = root["city"];
  const char* city = root["full"];
  const char* weather = root["weather"];
  double temp_f = root["temp_f"];
  const char* humidity = root["relative_humidity"];
  const char* wind_dir = root["wind_dir"];
  double wind_mph = root["wind_mph"];
  const char* pressure_in = root["pressure_in"];
  
  char myBuf[8] = "";
  
  // location of conditions
  snprintf_P(tempoutString1, (MAXARRAYSIZE - 1), PSTR("\nCity: %s, Condition: %s"), city, weather);
  dbg.println(tempoutString1);
  
  snprintf_P(tempoutString1, (MAXARRAYSIZE - 1), PSTR("Temp: %sF, Humidity: %s, Barometer %s in"), ftoa(myBuf, temp_f, 2), humidity, pressure_in);
  dbg.println(tempoutString1);
  
  snprintf_P(tempoutString1, (MAXARRAYSIZE - 1), PSTR("Wind Direction: %s, Speed: %s MPH\n"), wind_dir,  ftoa(myBuf, wind_mph, 2));
  dbg.println(tempoutString1);
}

Thanks in advance for your help.