I use Ethernet Shield and Arduino to GET data from the server in JSON format. Request looks like this:
client.println("GET http://ramp.local/api/actions?");
The response I get is:
[{"action_id":1,"action_type":"up","action_status":"new","ramp_id":31,"user_id":17},
{"action_id":2,"action_type":"down","action_status":"new","ramp_id":32,"user_id":20},
{"action_id":3,"action_type":"up","action_status":"completed","ramp_id":32,"user_id":17},
{"action_id":4,"action_type":"up","action_status":"failed","ramp_id":31,"user_id":17}]
How to collect a data in a string variable and parse it to get action_status
?
3 Answers 3
Ideally, you would use a proper recursive JSON parser, like the one suggested in prakharsingh95's answer. However, if code speed and size are critical considerations, and if the format of the response is narrowly constrained, then you can build a fast special-purpose parser.
Here is a simple example. It assumes the response has been stored in the
response
char array:
static const char key[] = "\"action_status\"";
const char *p, *q;
char action_status[16];
for (p = response; ; p = q) {
p = strstr(p, key); // find key
if (!p) break; // not found
p = strchr(p, ':'); // find ':' between key and value
p = strchr(p, '"'); // find opening quotes for the value
q = strchr(p+1, '"'); // find closing quotes
// Report finding.
strncpy(action_status, p+1, q-p-1);
action_status[q-p-1] = '0円';
Serial.print("Found action status: ");
Serial.println(action_status);
}
Of course, in production code you would check that every strchr
call
returns a non-NULL pointer. And you would check that the status you
found fits in your buffer.
Edit about the pros and cons of this method:
Compared to a proper JSON parser, this approach will give you smaller and faster code, the drawback is it being more fragile. For example, this will not detect a corrupted JSON, and it will return garbage if the action_status happens to be a number instead of a string, or is a string with embedded double quotes, or if the string "action_status" appears as a value of some other field... A full JSON parser should correctly handle all these cases.
On a non-embedded computer, a proper JSON parser would probably be the only appropriate answer. On a constrained microcontroller environment, you sometimes have to make trade-offs. In this particular instance, the "best" answer depends on how much you weight speed and size vs. robustness against unexpected input.
This is an arduino based, open source, JSON processor.
I would recommend a JSON parsing library. Checkout https://github.com/bblanchon/ArduinoJson
var response = [] ; // get response here
int response_length = 4; //Put length of the response array here
StaticJsonBuffer<200> jsonBuffer;
String action_ids[] = new String[response_length];
String action_types[] = new String[response_length];
String action_statuses[] = new String[response_length];
String ramp_ids[] = new String[response_length];
String user_ids[] = new String[response_length];
for (int i=0; i < response_length ; i++) {
JsonObject& data = jsonBuffer.parseObject(response[i]);
// Note the '&' above
action_ids[i] = data["action_id"];
action_types[i] = data["action_type"];
action_statuses[i] = data["action_status"];
ramp_ids[i] = data["ramp_id"];
user_ids[i] = data["user_id"];
}
Of course, you only need to extract those fields that you need.
-
Welcome to Arduino SE! Please do not abuse the edit functionality of our site by superfluous edits and rollbacks. To prevent misuse of the edit functionality here, I've locked this answer for a week; after this time, you will be able to edit your answer again. Thanks for your cooperation and feel free to reply with any questions.Anonymous Penguin– Anonymous Penguin2015年06月04日 15:06:50 +00:00Commented Jun 4, 2015 at 15:06