Decode JSON from Web to array

Hi,

I am quite new to Arduino and am trying to build a simple RFID door system. I have the reader part working fine on a local level with the allowed ID's stored in an array. However I would like to have a web-based system whereby I can add ID's online. The issue I am having is that my friend is sending the data from the web part in the JSON format and I need to decode this and convert it into different arrays so that the arduino can process the data. I have never used JSON so have no idea where to start. I have tried searching for the various libraries but am still quite confused. Basically I need to get some data from say http://mydata.co.uk/data.php and then return the result into a number of variables / arrays with the id number and a yes or no response form the server. Similarly I need to be able to send JSON data back to the server.

Thanks in advanced.

1 Like

This should be a good library for what you are trying to do: GitHub - bblanchon/ArduinoJson: 📟 JSON library for Arduino and embedded C++. Simple and efficient.

Two questions:

  1. Are you capable of getting information from the web currently?

  2. Do you have the JSON that you're trying to parse?

Yes I am currently reading part of the JSON string on a test site which simply displays the date and a random string of numbers. This is hosted on an online web server.

Thanks

Okay, seems like you've got the hard part done!

Could you post the JSON that's being retrieved and your code if possible? Then I'll be able to help you change stuff.

Thanks

Sorry about the delay,
Here is my code:

#include <aJSON.h>

#include <Ethernet.h>
#include <SPI.h>


byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte gw[] = {192,168,1,254};
byte server[] = { 51, 255, 42, 54 }; 
byte subnet[] = { 255, 255, 255, 0 };

EthernetClient client;

void setup()
{
  Ethernet.begin(mac, ip, gw, gw, subnet);
  Serial.begin(9600);

  delay(1000);

  Serial.println("connecting...");

  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.println("GET /time.php HTTP/1.0");
    client.println();
  } else {
    Serial.println("connection failed");
  }
}

void loop()
{
  boolean currentLineIsBlank = true;
  if (client.available()) {
    char c = client.read();
    client.println(c);
  }
  

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
  }

and the JSon and I am trying to decode is:

{"date":"03/12/2016","request_time":1480789006}

So, I'm assuming when you run this you print out a lot more information than just the JSON. Correct?

Could you run this code for me and post everything that is being printed out to the serial console? I'm afraid there might be some parsing that must be done before we get to parsing the JSON.

Thanks

I'm afraid there might be some parsing that must be done before we get to parsing the JSON.

I can't imagine why. The JSON data starts with a { and ends with a }. The techniques in Serial Input Basics - Updated show how to read, and store important data, defined by start and end markers.

Once the data is stored, parsing that particular JSON data is pretty simple.

Of course, that code runs exactly once, collects and prints, but does not save the data, and then goes into an infinite loop doing nothing, so it is NOT a good basis for a real program. Personally, I would expend no more effort on making something useful from that example.

xniinja:
So, I'm assuming when you run this you print out a lot more information than just the JSON. Correct?

Could you run this code for me and post everything that is being printed out to the serial console? I'm afraid there might be some parsing that must be done before we get to parsing the JSON.

Thanks

I've been doing a bit more work to the code and now have the following:

#include <ArduinoJson.h>



#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte gw[] = {192,168,1,254};
byte server[] = { 51, 255, 42, 54 }; // Google
byte subnet[] = { 255, 255, 255, 0 };

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

char json[] = "{\"date\":\"04/12/2016\",\"request_time\":1480852521}";
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  jsoncheck();
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
    
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip, gw, gw, subnet);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /time.php");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}

void jsoncheck(){
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(json);
  const char* date = root["date"];
  long request_time  = root["request_time"];
  Serial.print("Date:");
  Serial.println(date);
  Serial.print("Request_Time:");
  Serial.print(request_time);
}

This actually seems to be working now. However it still won't decode the JSON from my webserver. I believe it is because the formatting is different. Up the top of this code I have declared a variable "char json" which has the format recommended by the library but the code I am being sent is in a different format. Is there any way of easily converting it from the format sent by the php to something the library can recognise?

Thanks

The serial monitor displays:

Date:04/12/2016
Request_Time:1480852521
1 Like

Is there any way of easily converting it from the format sent by the php to something the library can recognise?

Of course.

Of course, it is easier if you tell us what you ACTUALLY get, and what actually happens when the real code that you didn't post tries to parse it.

    client.println("GET /time.php");
    client.println("Host: www.google.com");

I am absolutely certain that google is NOT hosting your time.php script.

No google is not hosting the php script. That was the example http client that I was adapting with the JSon code.

When changed to the web server I get no data as shown below:

Date:
Request_Time:0

My code is currently:

#include <ArduinoJson.h>



#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte gw[] = {192,168,1,254};
byte server[] = { 51, 255, 42, 54 }; // Google
byte subnet[] = { 255, 255, 255, 0 };

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

char json[] = "";
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  jsoncheck();
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
    
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip, gw, gw, subnet);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /time.php");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    json[0] = c;
    jsoncheck();
    
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}

void jsoncheck(){
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(json);
  const char* date = root["date"];
  long request_time  = root["request_time"];
  Serial.print("Date:");
  Serial.println(date);
  Serial.print("Request_Time:");
  Serial.print(request_time);
}
char json[] = "";

How many characters can this array hold?

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  jsoncheck();

What is the purpose of calling jsoncheck with an empty string?

  if (client.available()) {
    char c = client.read();
    json[0] = c;
    jsoncheck();
   
  }

What is the purpose of calling jsoncheck() with ONE character? How much data do you think you can embed in one character?

I suggest that you re-read reply #6 as many times as it takes until the information sinks in.

As I say, I am new to Arduino. I was simply trying to put the data collected from the webserver (c) into the json array so that I can then decode it using the library. That is where I am stuck. Re-reading response #6 has not really helped as there is no information to take in.

The calling of the jsoncheck in the setup was obviously something from a previous attempt which I forgot to remove. As you say there is no point in doing that so I'll remove that. The json[0] is because I wasnt sure how to put all the JSon data received into a useful variable whereby I can use it in the library.

Thanks

I was simply trying to put the data collected from the webserver (c) into the json array so that I can then decode it using the library.

The array is sized to hold one character. The link I posted shows how to read data using start and end markers, and store it in a large enough array.

That is where I am stuck

You can NOT store "{"date":"03/12/2016","request_time":1480789006}" in a one element array.

You have NOT proven that this is what the server sends back.

Re-reading response #6 has not really helped as there is no information to take in.

Complete nonsense.

If that is your attitude, you might as well admit defeat now.