1

I'm running this on a Particle Photon, but I think the issue is just me failing at C++. I'm trying to retrieve some JSON data from a HTTP API, convert it to JSON, and then extract a few values for display on the screen. I convert the String to a char array for the JSON parser, but it seems to only grab the first 10 characters of the String (unless I manually set length to a number shorter than 10), and then of course, the JSON parser fails.

Here's the relevant bit of code:

int str_len = response.body.length() + 1; 
tft.print("Length: "); tft.println(str_len);
char char_array[str_len];
response.body.toCharArray(char_array, str_len);

response.body is a big JSON string, but char_array is always just the first 10 characters of it: {"metadata

Another thing I noticed just now that might be related, str_len is usually reported to be ~500 characters, but when I hit the same URL in a browser it ends up more like ~1500 characters. Neither are pretty-printed, so I'm not sure what the discrepancy is.

Here's my complete code, except I removed the base64'd username and password from the Authorization header:

#include "HttpClient/HttpClient.h"
#include "SparkJson/SparkJson.h"
#include "Adafruit_mfGFX/Adafruit_mfGFX.h"
#include "Adafruit_SSD1351_Photon/Adafruit_SSD1351_Photon.h"

// OLED - You can use any (4 or) 5 pins
#define sclk A3
#define mosi A5
#define dc   D7
#define cs   A2
#define rst  D5

// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF


// Option 1: Hardware SPI - uses some analog pins, but much faster
Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst);

// Option 2: Software SPI - use any pins but a little slower
//Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, mosi, sclk, rst);  


HttpClient http;

// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    //  { "Content-Type", "application/json" },
    { "Authorization", "Basic <snip>" }, // base64encode(username:password)
    { "Accept" , "application/json" },
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;


void setup(void) {

    tft.begin();

    tft.fillScreen(BLACK);
    tft.setCursor(0,0);
    tft.setTextSize(0);
    tft.setTextColor(WHITE);

    // http://twcservice.mybluemix.net/api/weather/v2/observations/current?units=e&geocode=40.0388067%2C-84.3428471&language=en-US
    request.hostname = "twcservice.mybluemix.net";
    request.port = 80;
    request.path = "/api/weather/v2/observations/current?units=e&geocode=40.0388067%2C-84.3428471&language=en-US";
    //request.body = "{\"key\":\"value\"}";
    http.get(request, response, headers);

    tft.print("Status: ");
    tft.println(response.status);

    //tft.println("Response Body: ");
    //tft.println(response.body);

    int str_len = response.body.length() + 1; 
    tft.print("Length: "); tft.println(str_len);
    char char_array[str_len];
    response.body.toCharArray(char_array, str_len);

    DynamicJsonBuffer jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(char_array);

    if (root.success()) {
        tft.print("Current Temperature: "); 
        const char* temp = root["observation"]["imperial"]["temp"];
        tft.println(temp);
    } else {
        tft.setTextColor(RED);
        tft.println("parseObject() failed");

        tft.setTextColor(GREEN);
        uint32_t freemem = System.freeMemory();
        tft.print("Free memory: "); 
        tft.print(freemem/1024); 
        tft.println("k");

        tft.setTextColor(WHITE);
        tft.println(char_array);

        tft.setTextColor(CYAN);
        tft.println(response.body);
    }
}

void loop() {

}

The actual printout on the screen is smething like

Status: 200
Length: 501
parseObject() failed
Free memory: 59k
{"metadata
{"metadata":{"language":"en-US","transaction_id":"1460309558940:-660053703","version":"1","latitude":40.04,"longitude":-84.34,"units":"e","expire_time_gmt":1460310025,"status_code":200},"observation":{"class":"observation","expire_

Finally, here's an example of the JSON response I'm trying to parse:

{"metadata":{"language":"en-US","transaction_id":"1460309558940:-660053703","version":"1","latitude":40.04,"longitude":-84.34,"units":"e","expire_time_gmt":1460310025,"status_code":200},"observation":{"class":"observation","expire_time_gmt":1460310025,"obs_time":1460307900,"obs_time_local":"2016-04-10T13:05:00-0400","wdir":160,"icon_code":26,"icon_extd":2690,"sunrise":"2016-04-10T07:06:23-0400","sunset":"2016-04-10T20:11:13-0400","day_ind":"D","uv_index":3,"uv_warning":0,"wxman":"wx4400","obs_qualifier_code":null,"ptend_code":2,"dow":"Sunday","wdir_cardinal":"SSE","uv_desc":"Moderate","phrase_12char":"Cloudy/Wind","phrase_22char":"Cloudy/Wind","phrase_32char":"Cloudy/Wind","ptend_desc":"Falling","sky_cover":"Cloudy","clds":"OVC","obs_qualifier_severity":null,"vocal_key":"OT48:OX2690","imperial":{"wspd":20,"gust":24,"vis":10.000,"mslp":1018.7,"altimeter":30.09,"temp":48,"dewpt":27,"rh":43,"wc":41,"hi":48,"temp_change_24hour":11,"temp_max_24hour":44,"temp_min_24hour":27,"pchange":-0.10,"feels_like":41,"snow_1hour":0.0,"snow_6hour":0.0,"snow_24hour":0.0,"snow_mtd":1.2,"snow_season":21.3,"snow_ytd":21.3,"snow_2day":0.7,"snow_3day":0.8,"snow_7day":0.9,"ceiling":7400,"precip_1hour":0.00,"precip_6hour":0.00,"precip_24hour":0.00,"precip_mtd":1.10,"precip_ytd":11.76,"precip_2day":0.29,"precip_3day":0.30,"precip_7day":0.96,"obs_qualifier_100char":null,"obs_qualifier_50char":null,"obs_qualifier_32char":null}}}

Any idea what's going on?

  • Probably something specific to the Particle Photon. I can convert that string to and from String/char array quite happily on a Mega2560. – Majenko Apr 10 '16 at 20:46
  • I tried it with the string hard-coded just now and that worked as expected. So maybe there's something funky with the HttpClient? – Nathan Friedly Apr 10 '16 at 21:14
1

It turns out that the HttpClient library has a fixed response length limit of 1024 bytes and whatever it was doing after it hit that limit is what caused all of the trouble.

Forking the library and increasing the limit as recommended at https://community.particle.io/t/issues-with-string-char-array-length-json-parsing/21980 solved the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.