Разделение элементов массива JSON как строки в C - PullRequest
0 голосов
/ 05 марта 2019

У меня есть простая веб-страница, которая отображает объект json в <body>.Я упростил пример здесь, так как каждый элемент имеет много данных, и нет необходимости распечатывать его в этом вопросе.Однако я сохранил формат, включая возврат каретки.

<body>
    callBack({
    "resSet":[
        {
        "results":[


{^M
"res":{"data inside res",^M
       "more data",^M
       {"and some more"}^M
},^M

{^M
"res":{"data inside res",^M
       "more data",^M
       {"and some more"}^M
},^M

{^M
"res":{"data inside res",^M
       "more data",^M
       {"and some more"}^M
}],^M
    "other resSet data"^M
}^M
],
})^M
</body>

Я использую libcurl в C для чтения этих данных в виде строки в память.Я использую C и CURL для поддержания портативности и контроля памяти.То, что я хочу сделать, это отделить элементы массива "results", чтобы я мог изменить их порядок, как я выберу.После сортировки json записывается в файл для других программ.

Обратите внимание, что он может иметь структуру объекта JSON, но он обрабатывается как строка в памяти.

Здесьмой код.

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

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

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) 
// curl callback function (found on 
https://curl.haxx.se/libcurl/c/getinmemory.html)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;

  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) {
    /* out of memory! */
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }

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

  return realsize;
}

int main(int argc, char *argv[]) { // pass query and collection
  curl_global_init(CURL_GLOBAL_ALL);
  CURL *curl;
  CURLcode res;
  struct MemoryStruct chunk;
  char *url = calloc(1024, 1); // url to maxxcat4.astm.org/query4.cgi, plenty of space for query and collection parameters
  char *query = calloc(strlen(argv[1])+1, 1); // +1 so | can be placed in function FetchLine
  char *collection = calloc(strlen(argv[2]), 1);
  char *order; // not allocated, points to return from function FetchLine

  sprintf(query, "%s", argv[1]);
  sprintf(collection, "%s", argv[2]);
  sprintf(url, "http://maxxcat4.astm.org/query4.cgi?query=%s&collection=%s", query, collection); // query then collection

  chunk.memory = malloc(1); // currently using realloc, should change to calloc
  chunk.size = 0; // nothing, initially

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, url); // fetch data from url
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,WriteMemoryCallback); // send the data to the function WriteMemoryCallback (found on https://curl.haxx.se/libcurl/c/getinmemory.html)
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); // pass the MemoryStruct chunk to the function
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); // set a user agent if the server requests for one
    res = curl_easy_perform(curl); // retrieve data

    if(res != CURLE_OK) { // make sure things worked
      fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    } else {
      /*
        Sort the data while in memory according to how the file is shuffled
        - read file into memory
        - take one line at a time, breaking on delimiter (if needed)
        - shuffle each res
      */
      // order = FetchLine(query);

      FILE *fp;
      fp = fopen("maxxcat4_data.json", "w");

      /* seperate results array elements here */

      fclose(fp);
      printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
    }
    /* always cleanup */
    curl_easy_cleanup(curl); // clean up handle
    free(chunk.memory);
    free(url);
    free(query);
    free(collection);
    free(order);
    curl_global_cleanup(); // clean up libcurl
  }
  return 0;
}

Моей первой идеей было использование strtok(), но я не знаю способа разграничить строку, а не один символ из набора разделителей.Я читал о json-c , но я хочу избежать подобных зависимостей, если это вообще возможно.Как я могу отделить элементы?

1 Ответ

0 голосов
/ 05 марта 2019

Однако я сохранил формат, включая возврат каретки.

Если вы знаете этот точный формат, вы можете воспользоваться этими знаниями и упростить чтение - например, каждый элементрезультаты заканчиваются на } в начале строки.

Следующий фрагмент кода разделяет строку в chunk.memory на head (часть перед элементами результата), res[nres] (массивnres элементы) и tail (часть после элементов результата, после закрытия ]);комментарии встроены в код.

    char c, *head, **res = NULL, *tail; // pointers to parts
    int nres = 0;                       // number of results
    head = chunk.memory;                // it begins here
    const char results[] = "\"results\":[";
    char *cp = strstr(head, results);   // find the results
    if (!cp) printf("%s not found\n", results), exit(1);
    cp += strlen(results);              // skip to the \n
    *cp++ = '\0';                       // delimit the head
    do
    {
        res = realloc(res, sizeof *res * ++nres);
        if (!res) puts("out of memory"), exit(1);
        res[nres-1] = cp;               // store the result
        cp = strstr(cp, "\n}");         // find end of result
        if (!cp) puts("} not found"), exit(1);
        cp += 2;                        // skip over the }
        c = *cp;                        // character after } is , or ]
        *cp++ = '\0';                   // delimit the string
    } while (c == ',');
    if (c != ']') puts("] not found"), exit(1);
    tail = cp;                          // rest follows here
    // output the parts with results rearranged, e. g. backwards
    printf("%s\n", head);
    while (nres--) printf("%s%c", res[nres], nres ? ',' : ']');
    free(res);
    printf("%s", tail);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...