How do I create a JSON object in C? - c

I currently have a string in C that I have coded like this:
#define MESSAGE_STRING "{\"deviceName\":string, \"Telemetry\":{\"voltage\":12,\"current\":0.12}}"
As I am sending it to a cloud service that processes it as a JSON message and receives this:
But I want to do this in an easier way as this could get a lot more complex when I am sending more complicated JSON messages. I was wondering if there was any easy way to create these JSON objects within C easier?
Cheers

Write your JSON in a text file, and replace every parameter with a %d, %f, %s placeholder.
Then read this file, and fill in the values with sprintf()
But pay attention to the order of your parameters.
json.txt:
{
"device_name": "%s",
"Telemetry": {
"voltage": %d,
"current": %f
}
}
main.c
#include <stdio.h>
int main(void)
{
char json_format[4096];
char message_string[4096];
FILE* fp;
// Read in json format
fp = fopen("json.txt", "r");
int len = fread(json_format, 1, 4096, fp);
json_format[len] = '\0';
fclose(fp);
// Fill in parameters
const char* device_name = "string";
int voltage = 12;
float current = 0.12;
sprintf(message_string, json_format, device_name, voltage, current);
printf("%s", message_string);
}
The code is only for understanding the concept.
It works, but don't use it, because it doesn't check for erorrs and the memory management is bad too.

Related

How to read a formated chain until a certain point in C?

I am currently struggling with file manipulations in C and still have a lot of reflexes to acquire.
My code is here :
int main(int argc, char *argv[])
{
FILE* f = fopen("/Users/[...].txt","r+");
int input1=0; int input2=0; int input3=0;
fscanf(f,"sommets : %d\n",&input1);
printf("%d\n",input1);
fscanf(f,"transitions : %d\n",&input1);
printf("%d\n",input1);
printf("%ld\n",ftell(f));
fscanf(f,"ARCS PRE\n");
printf("%ld\n",ftell(f));
long int point = ftell(f);
char word[10]="ARCS POST"; char data[100];
while((strcmp(word, fgets(data,100,f)))!=0){
fseek(f,point-ftell(f), (int) ftell(f)); //to reposition the cursor after strcmp
fscanf(f, "%d->%d,%d\n", &input1, &input2, &input3);
printf("%d->%d,%d\n",input1, input2, input3);
point =ftell(f);
}
fclose(f);
return 0;
}
The part which is not working is around the while : here is the file I try to read
sommets : 69
transitions : 9
ARCS PRE
1->2,5
1->3,7
ARCS POST
1->7,1
1->9,4
END
The while is supposed to stop the reading once I reach "ARCS POST" in the file but never recognizes such a string, and it seems that the fseek in the loop doesn't want to work. In fact I also tried with SEEK_CUR but its value seems stuck to 1. Does anyone have an alternative for what I am trying to do ? Or does anyone know why nothing goes on this part as intended ?

Parse C char array sent via web server into (JSON or JavaScript) variables

Desired outcome: Send a struct of GPS data from C using a web server and have the data ( lat, long, etc.) display on a web page.
Using: Linux, libwebsockets (LWS) library for web server. C code is implemented as a standalone plugin in the LWSWS (web server) app.
Current understanding/work on project: Casting struct from plugin to a char array and trying to parse the array (using JSON) into the individual members of the original struct. Then display each variable on a web page.
I am new to Linux, LWS, HTML, JavaScript, and JSON. I can use JSON or Javascript to work with the variables, whichever makes more sense. I am not completely sure of my plan on either side (C/JS) of this part of the project.
What is the best way to transfer this information and convert for use on the web page?
Here is my struct:
struct per_session_data__gps_rcvr {
struct time_struct{
int month;
int day;
int year;
int hour;
int minute;
double second;
}time;
double latitude;
char lat_indicator;
double longitude;
char lon_indicator;
double heading;
int quality;
int satellites;
};
Sending struct out, cast to a char pointer:
// Write GPS data to GUI
n = lws_snprintf( (char *)p, sizeof(buf) - LWS_PRE, "%s", (char *)pss );
m = lws_write(wsi, p, n, LWS_WRITE_TEXT);
if (m < n) {
lwsl_err("ERROR %d writing to di socket\n", n);
return -1;
}
break;
The test code I am modifying appears to receive data in a variable called "msg". I am assuming I need to parse the data sent in the char array into chunks that correspond to the members of the original struct. Then I can display each piece of GPS data on the web page.
var socket_gps;
if (use_lws_meta)
socket_gps = lws_meta.new_ws("", "gps-rcvr-protocol");
else
socket_gps = new_ws(get_appropriate_ws_url(""), "gps-rcvr-protocol");
try {
socket_gps.onopen = function() {
document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
document.getElementById("wsdi_status").innerHTML =
" <b>websocket connection opened</b><br>" +
san(socket_gps.extensions);
}
socket_gps.onmessage =function got_packet(msg) {
document.getElementById(" **VARIABLE GOES HERE** ").textContent = msg.data + "\n";
}
socket_gps.onclose = function(){
document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
}
}
catch(exception) {
alert('<p>Error' + exception);
}
Please let me know if there is a better way to send the data out from C, and/or if I have correctly configured the data. In my research, it was mentioned that data could be sent as binary, but sending plain text messages and using JSON seemed like a better plan.
It looks like JSON can "stringify" info, but only if it's typed in or in JavaScript format already? I'm not sure. I have not seen any way to parse out a char array, a set number of characters at a time, and save those segments as variables on the HTML side. That is what I was hoping for.
Thank you for your suggestions!
Like this:
n = snprintf( (char *)p, sizeof(buf), "{\"NameofParam1\":\"%d\",\"NameofParam2\":\"%d\"}", param1, param2 );
That gives you your whole JSON string in one go (stored in buffer). Just use the appropriate flag (%s, %X, %c, %f, etc.) to capture your parameter.

C Transforming array into string using sprintf

I have scanned "ABCDEFGHIJK" with fscanf into a char array[26]. Then I got "ABCDEFGHIJK" using "for" into another array[11]. Now I need to get to an "ABCDEFGHIJK.mp4" array[15] in order to feed that filename into a rename function.
I don't know much about C programming besides printf, scanf, for and while.
sprintf(filename, "%c%c%c%c%c%c%c%c%c%c%c.mp4", codigo[0], codigo[1], codigo[2], codigo[3], codigo[4], codigo[5], codigo[6], codigo[7], codigo[8], codigo[9], codigo[10]);
This code above seems to work, but I wonder if there is a simpler way (especially for bigger arrays)?
Clarification: I have a txt file, formatted with these containing the filenames without extension and the human filename. I'm trying to make a program that will rename these files to the correct name, as they are from a backup that failed.
EDIT: Here is the full program. I renamed the variables to make more sense, so "codigo" is now "idcode".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int i, j, k;
char value1[26], value2[70], idcode[11], filename[16], fullname[64], filenamestring[16], fullnamestring[64];
// Opening file.
FILE *nomes;
nomes = fopen("/Users/EA/Desktop/Songs/backup.txt", "rt");
if(nomes == NULL)
{
printf("Erro ao abrir backup.txt");
exit(1);
}
// Skipping beggining of file until first value.
for(i=0; i<10; i++)
{
fscanf(nomes, "%*s");
}
// Reading first value, and repetition.
while(fscanf(nomes, "%s", value1) == 1)
{
j = k = 0;
// Extracting idcode from value1.
for(i=7; i<18; i++)
{
idcode[j] = value1[i];
j++;
}
// Filling the complete filename.
sprintf(filename, "%.*s.mp4", 11, idcode);
// Reading second value, the "human" filename.
fscanf(nomes, "\n%[^\n]", value2);
for(i=6; i<70; i++)
{
fullname[k] = value2[i];
k++;
}
// Transforming filenames into strings for rename function.
strncpy(filenamestring, filename, 16);
strncpy(fullnamestring, fullname, 64);
// Renaming the files.
rename(filename, fullname);
// Skipping useless data before the next cycle.
for(i=0; i<9; i++)
{
fscanf(nomes, "%*s");
}
}
// Closing file and ending program.
fclose(nomes);
return(0);
}
It looks like you got an array of char's.
You can simply do:
sprintf(filename, "%.*s.mp4", 11, codigo)
You can read more about the %.*s specifier in this question.
If you just want to append the format ".mp4" to the end of the string the easiest way to do that is just:
strcat(filename,".mp4");
after you printed the name without the ".mp4" into it.
If you really want to use sprintf then i think this should suffice:
sprintf(filename,"%s.mp4", codigo);
Also,if you want your string to be bigger and not fixed in size you can put "\0" at the end of it(this might not work if you try to use the strings in other programming languages but c) with strcat as above,or you can do this:
memset(&filename, 0, sizeof(filename));

Converting C #define constants into variables

I have a device driver where the access to the wifi-router are hard coded using the #define macros in C. where the code looks like:
#define SSID "XXXX-XXX"
#define AUTH AAAA
#define PSK “YYyy00”
and the function that use these user defined constants is defined as:
router_connect((char *)SSID, sizeof(SSID), AUTH, (char *)PSK, CH_ALL);
I'd like to be change these constants as defined .h file as strings that I can read from a SD card and pass it to the function call rather than as hard coded in the main.h file. I'd like to have the ability to change them rather them as stored as fixed ones coded inside a program. After all they are user defined strings, as long as the values are correctly passed between the devices they don't need to be hard coded in the main code.
So I wrote them in the main.c as:
extern char SSID[] = "XXXX-XXX";
extern uint8 AUTH = AAAA;
extern char PSK[] = "YYyy00";
and in the SD card I have a file setup.txt where I entered the three strings as below in three lines:
XXXX-XXX;
AAAA;
YYyy00;
I wrote a little routine to read each line from the SD card and assign the strings to the variables
SSID, AUTH, PSK
char line[20];
int line_count;
FRESULT my_res;
FIL myfil;
my_res = f_open(&myfil, "setup.txt", FA_READ);
if (my_res != FR_OK) {
printf("file: setup.txt is not found. \n\r");
/* deal with errors */;
}
for (line_count = 1; line_count < 4;) {
f_gets(line, sizeof(line), &myfil);
if (line_count == 1) {
strcpy(SSID, line);
printf("SSID: %s %s \n\r", SSID, line);
}
if (line_count == 2) {
strcpy(AUTH, line);
printf("AUTH: %s %s \n\r", AUTH, line);
}
if (line_count == 3) {
strcpy(PSK, line);
printf("PSK: %s %s \n\r", PSK, line);
}
line_count++;
}
My intent was to read these strings from the SD card before the function "router_connect" is called.
I can do that with no problem, when I print out the stings I read from the SD card they are exactly like when they are hard coded, but I find the "router_connect" function does not like the parameters I'm passing. The device driver works when I hard code the values in the #define statement but for some reason it is not passing the values correctly to the function. Can you please advise if I'm doing it incorrectly for passing parameters to the function call and what will be the right way to achieve it. Thanks.
Firstly, it would be nice to see how exactly the function doesn't like those parameters. Secondly, I see that you read the AUTH value as a char array, and what the function wants is a uint8. How do you pass it? Maybe parsing AUTH into an uint8 would do the trick.

Using a function to read in a file

I have the code below which compiles fine in xcode, but when I take it across to Microsoft Visual studio I get a bunch of errors.
void openfile(int mapArray[MAX_HEIGHT][MAX_WIDTH], int *interest, int *dimension1, int *dimension2)
{
int counter = 0;
char buffer;
int rowss, colss;
*interest = 0;
FILE *f;
f = fopen(FILENAME, "r");
if (f==NULL) {
printf("Map file could not be opened");
return 0;
}
// create char array the dimensions of the map
fscanf(f, "%d %d" , dimension1, dimension2 );
// printf("%d %d\n" , dimensions[0], dimensions[1]);
// Reads the spaces at the end of the line till the map starts
buffer=fgetc(f);
while (buffer!='*') {
buffer=fgetc(f);
}
// Read the txt file and print it out while storing it in a char array
while (buffer!=EOF) {
mapArray[rowss][colss]=buffer;
colss++;
// Count up the points of interest
if (((buffer>64)&&(buffer<90))||(buffer=='#') ) {
counter++;
}
// resets column counter to zero after newline
if (buffer=='\n') {
colss=0;
rowss++;
}
buffer=fgetc(f);
}
// Closes the file
fclose(f);
*interest=counter;
}
Which parts are creating all the errors?
I get this list of errors when attempting to compile
Thanks in advance.
I see a few immediate problems. First, you're not initialising rowss or colss before you use them, hence they could contain any value.
Second, fgetc() returns an int so that you can detect end of file. By using a char to hold the return value, you're breaking the contract with the standard library.
Thirdly, you return a 0 if the filename couldn't be opened, despite the fact that the function is specified to return void (ie, nothing).
No doubt those are three of the errors the compiler picked up on, there may be others, and you should probably post the error list with your question for a more exhaustive analysis.

Resources