zserge / jsmn

Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket
MIT License
3.65k stars 778 forks source link

jsmn_parse in loop results: Object expected Error #181

Open forest-roby opened 4 years ago

forest-roby commented 4 years ago

Dear All, I am playing with JSMN for the first time. It is working for my purposes but I would like to run it in a loop, continouly updating information. When I run the function for the first time everything works, after that in each loop I receive: Object expected error message. here is the code: (you have to get your own api key )

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <conio.h>
#include <jsmn.h>

struct memory{
    char* memory;
    size_t size;
};

static size_t writecallback(char* contents, size_t size, size_t nmemb, void *userp){

    size_t realsize = size * nmemb;
    struct memory* mem = (struct memory*)userp;

    char *ptr = (char*) realloc(mem->memory, mem->size + realsize + 1); //VC++ miatt kell a (char*) a realloc elé.
    if (ptr == NULL)
        return(0);

    mem->memory = ptr;
    memcpy(&mem->memory[mem->size], contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
    return realsize;

    //fprintf(stderr, "\r%s", contents);
    //fflush(stdout);
    //return size * nmemb;
}

//jsmn
static const char *JSON_STRING = "";

static int jsoneq(const char* json, jsmntok_t* tok, const char* s) {
    if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start &&
        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
        return 0;
    }
    return -1;
}
//JSMN vége

int get_coordinates(double *lat, double *lon, double *alt, double *azi, double *ele, double *_ra, double *_dec, long long *_times) {

    CURL* curl;
    CURLcode res;
    struct memory chunk;

    chunk.memory = NULL;
    chunk.size = 0;
    curl_global_init(CURL_GLOBAL_ALL);

    //jsmn rész
    int i = 0;
    int r = -1;
    jsmn_parser p;
    jsmntok_t t[500]; /* We expect no more than 128 tokens */
    //jsmn rész vége

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://www.n2yo.com/rest/v1/satellite/positions/25544/46.3185/17.7515/0/1/&apiKey=*HERE IS MY KEY*");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() returned %s\n",
                curl_easy_strerror(res));
        }
        else {
            //Itt töltöttük le az adatokat:
            //printf("We got %d bytes to our callback. We received the following text:\n\n", (int)chunk.size);
            printf("%s\n\n", chunk.memory);
            //
            //  JSMN próba
            //
            static const char* JSON_STRING = chunk.memory;

            jsmn_init(&p);
            r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t,
                sizeof(t) / sizeof(t[0]));
            if (r < 0) {
                printf("Failed to parse JSON: %d\n", r);
                return 1;
            }

            /* Assume the top-level element is an object */
            if (r < 1 || t[0].type != JSMN_OBJECT) {
                printf("Object expected\n");
                //printf("%d\n", r);
                //printf("%d\n", t[0]);
                return 1;
            }

            /* Loop over all keys of the root object */
            for (i = 1; i < r; i++) {
                if (jsoneq(JSON_STRING, &t[i], "user") == 0) {
                    /* We may use strndup() to fetch string value */
                    printf("- User: %.*s\n", t[i + 1].end - t[i + 1].start,
                        JSON_STRING + t[i + 1].start);
                    i++;
                }
                else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) {
                    /* We may additionally check if the value is either "true" or "false" */
                    printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start,
                        JSON_STRING + t[i + 1].start);
                    i++;
                }
                else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) {
                    /* We may want to do strtol() here to get numeric value */
                    printf("- UID: %.*s\n", t[i + 1].end - t[i + 1].start,
                        JSON_STRING + t[i + 1].start);
                    i++;
                }
                else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) {
                    int j;
                    printf("- Groups:\n");
                    if (t[i + 1].type != JSMN_ARRAY) {
                        continue; /* We expect groups to be an array of strings */
                    }
                    for (j = 0; j < t[i + 1].size; j++) {
                        jsmntok_t* g = &t[i + j + 2];
                        printf("  * %.*s\n", g->end - g->start, JSON_STRING + g->start);
                    }
                    i += t[i + 1].size + 1;
                }
                else {
                    //
                    //printf("%.*s, i: %d\n", t[i].end - t[i].start, JSON_STRING + t[i].start, i);
                    //strncpy_s(tomb, t[i].end - t[i].start, JSON_STRING + t[i].start, t[i].end - t[i].start);
                }
            }
            //printf("% .*s: % .*s\n", t[1].end - t[1].start, JSON_STRING + t[1].start, t[2].end - t[2].start, JSON_STRING + t[2].start);
            //printf("% .*s: % .*s\n", t[5].end - t[5].start, JSON_STRING + t[5].start, t[6].end - t[6].start, JSON_STRING + t[6].start );
            //printf("% .*s: % .*s\n", t[7].end - t[7].start, JSON_STRING + t[7].start, t[8].end - t[8].start, JSON_STRING + t[8].start);

            sscanf_s((JSON_STRING + t[13].start), "%lf", lat);
            sscanf_s((JSON_STRING + t[15].start), "%lf", lon);
            sscanf_s((JSON_STRING + t[17].start), "%lf", alt);
            sscanf_s((JSON_STRING + t[19].start), "%lf", azi);
            sscanf_s((JSON_STRING + t[21].start), "%lf", ele);
            sscanf_s((JSON_STRING + t[23].start), "%lf", _ra);
            sscanf_s((JSON_STRING + t[25].start), "%lf", _dec);
            sscanf_s((JSON_STRING + t[27].start), "%d", _times);

            //
            //JSMN vége
            //
        }

        free(chunk.memory);
        curl_easy_cleanup(curl);

    }
    curl_global_cleanup();

return(0);
};

int main(void) {

    double latitude, longitude, altitude, azimuth, elevation, ra, dec;
    long long timestamp;
    int c = 1;

    //-------------------------------------------------------------------
        while (c != 'n')             // until correct key is pressed
        {
            do {                    // forever
                //do
    //
    get_coordinates(&latitude, &longitude, &altitude, &azimuth, &elevation, &ra, &dec, &timestamp);
    printf("\nLatitude:\t%lf", latitude);
    printf("\nLongitude:\t%lf", longitude);
    printf("\nAltitude:\t%lf", altitude);
    printf("\nAzimuth:\t%lf", azimuth);
    printf("\nElevation:\t%lf", elevation);
    printf("\nRa:\t\t%lf", ra);
    printf("\nDec:\t\t%lf", dec);
    printf("\nTimestamp:\t%ld", timestamp);
    printf("\n");
    //-------------------------------------------------------------------
            //do
            } while (!_kbhit());      // until a key press detected
            c = _getch();            // fetch that key press
        }
    //

    return(0);
}

(Visual Studio 2019, windows 10)

The received text looks like this: {"info":{"satname":"SPACE STATION","satid":25544,"transactionscount":91},"positions":[{"satlatitude":-51.79721854,"satlongitude":-12.7783,"sataltitude":439.3,"azimuth":198.83,"elevation":-49.23,"ra":316.23335672,"dec":-77.09388627,"timestamp":1577393729}]}

I learned to program in C about 15 years ago in Linux - I was quite good at it and never used it since. I am sure the code is not elegant. First I want it to work. I appreciate any help you can provide.

Robert

forest-roby commented 4 years ago

I was too hasty asking your help! Farther bugging showed the error. Problem was with: JSON_STRING This change helped:

static const char* JSON_STRING = NULL; JSON_STRING = chunk.memory;