DaveGamble / cJSON

Ultralightweight JSON parser in ANSI C
MIT License
10.72k stars 3.21k forks source link

Problem parsing a JSON file #191

Closed ErosOlmi closed 7 years ago

ErosOlmi commented 7 years ago

I have to below JSON file. I cannot parse "Movimento" level. I'm able to get "ListaMovimenti" that is an object but if I use cJSON_GetObjectItem to get "Movimento" from "ListaMovimenti" I get back a null pointer.

{
  "status": {
    "code": "OK",
    "description": "Mock Transaction List retrieved successfully"
  },
  "error": {
    "description": ""
  },
  "payload": [
    {
      "ListaMovimenti": {
        "Movimento": [
          {
            "DataContabile": "03/06/2016",
            "Importo": "250,00",
            "Segno": "D",
            "Divisa": "EUR",
            "DataValuta": "03/06/2016",
            "Terminale": "215",
            "CausaleVariabile": "CP 0206 05156-32770 0230",
            "Controvalore": null,
            "NumeroOperazioneH2O": null,
            "NumeroProgressivoHost": "309825",
            "IdMovimentoH2O": null
          },
          {
            "DataContabile": "01/06/2016",
            "Importo": "593,41",
            "Segno": "D",
            "Divisa": "EUR",
            "DataValuta": "01/06/2016",
            "Terminale": "120",
            "CausaleVariabile": "PD ING BANK N.V. MILAN BR",
            "Controvalore": null,
            "NumeroOperazioneH2O": null,
            "NumeroProgressivoHost": "183157",
            "IdMovimentoH2O": null
          }
        ]
      }
    }
  ]
}
FSMaxB commented 7 years ago

This does work for me with the following code:

#include <stdio.h>
#include <stdlib.h>
#include <cjson/cJSON.h>

static const char json[] = "\n\
{\n\
  \"status\": {\n\
    \"code\": \"OK\",\n\
    \"description\": \"Mock Transaction List retrieved successfully\"\n\
  },\n\
  \"error\": {\n\
    \"description\": \"\"\n\
  },\n\
  \"payload\": [\n\
    {\n\
      \"ListaMovimenti\": {\n\
        \"Movimento\": [\n\
          {\n\
            \"DataContabile\": \"03/06/2016\",\n\
            \"Importo\": \"250,00\",\n\
            \"Segno\": \"D\",\n\
            \"Divisa\": \"EUR\",\n\
            \"DataValuta\": \"03/06/2016\",\n\
            \"Terminale\": \"215\",\n\
            \"CausaleVariabile\": \"CP 0206 05156-32770 0230\",\n\
            \"Controvalore\": null,\n\
            \"NumeroOperazioneH2O\": null,\n\
            \"NumeroProgressivoHost\": \"309825\",\n\
            \"IdMovimentoH2O\": null\n\
          },\n\
          {\n\
            \"DataContabile\": \"01/06/2016\",\n\
            \"Importo\": \"593,41\",\n\
            \"Segno\": \"D\",\n\
            \"Divisa\": \"EUR\",\n\
            \"DataValuta\": \"01/06/2016\",\n\
            \"Terminale\": \"120\",\n\
            \"CausaleVariabile\": \"PD ING BANK N.V. MILAN BR\",\n\
            \"Controvalore\": null,\n\
            \"NumeroOperazioneH2O\": null,\n\
            \"NumeroProgressivoHost\": \"183157\",\n\
            \"IdMovimentoH2O\": null\n\
          }\n\
        ]\n\
      }\n\
    }\n\
  ]\n\
}\n\
";

int main() {
    cJSON *payload = NULL;
    cJSON *listaMovimenti = NULL;
    cJSON *movimento = NULL;
    char *printed_movimento = NULL;

    cJSON *parsed_json = cJSON_Parse(json);
    if (parsed_json == NULL) {
        fprintf(stderr, "Failed to parse JSON.\n");
        return EXIT_FAILURE;
    }

    payload = cJSON_GetObjectItem(parsed_json, "payload");
    if (!cJSON_IsArray(payload)) {
        free(parsed_json);
        fprintf(stderr, "Failed to get payload or it isn't an array.\n");
        return EXIT_FAILURE;
    }

    if (payload->child == NULL) {
        free(parsed_json);
        fprintf(stderr, "Payload has no entries.\n");
        return EXIT_FAILURE;
    }

    listaMovimenti = cJSON_GetObjectItem(payload->child, "ListaMovimenti");
    if (!cJSON_IsObject(listaMovimenti)) {
        free(parsed_json);
        fprintf(stderr, "Failed to get ListaMoviementi or it isn't an object.\n");
        return EXIT_FAILURE;
    }

    movimento = cJSON_GetObjectItem(listaMovimenti, "Movimento");
    if (movimento == NULL) {
        free(parsed_json);
        fprintf(stderr, "Failed to get Movimento.\n");
        return EXIT_FAILURE;
    }

    printed_movimento = cJSON_Print(movimento);
    if (printed_movimento == NULL) {
        free(parsed_json);
        fprintf(stderr, "Failed to print Movimento.\n");
        return EXIT_FAILURE;
    }

    puts(printed_movimento);

    free(printed_movimento);

    return EXIT_SUCCESS;
}

If you show me the code you are using to get Movimento I might be able to spot the mistake.

ErosOlmi commented 7 years ago

Dear Max, thanks a lot for your code. Yes now it is working. My error was not to get child of Payload.

Regarding my code ... :)

I'm using your great library inside another language called thinBasic, a Basic like interpreter. I've compiled cJSON using VS2017 into a DLL and then wrap the DLL into a thinBasic module My thinBasic source is the following, quite close to your C code .

Thanks again. Eros

uses "Console"
uses "File"
uses "CJSon"

function tbmain() as Long

  dim parsed_json           as cJSON Ptr
  'dim pStatus         as cJSON Ptr
  'dim pError          as cJSON Ptr
  dim PayLoad        as cJSON Ptr
  dim ListaMovimenti as cjson ptr
  dim Movimento      as cjson ptr

  dim pItem      as cjson ptr

  string my_json_string = file_load(APP_SourcePath & "cjson_AccountMovements.json")

  parsed_json = cJSON_Parse(my_json_string)

  if getat(parsed_json) = %NULL Then
    printl "Failed to parse JSON."
    return .1
  end If

    payload = cJSON_GetObjectItem(parsed_json, "payload")

    if cJSON_IsArray(payload) = 0 Then
        cjson_delete(parsed_json)
        printl "Failed to get payload or it isn't an array.\n"
        return -1
    end If

    if cjson_item_getchild(payload) = %NULL then
        cjson_delete(parsed_json)
        printl "Payload has no entries.\n"
        return -1
    end if

  pItem = cjson_item_getchild(payload)
    listaMovimenti = cJSON_GetObjectItem(pItem, "ListaMovimenti")
    if cJSON_IsObject(listaMovimenti) = %null then
        cjson_delete(parsed_json)
        printl "Failed to get ListaMoviementi or it isn't an object.\n"
        return -1
    end if

    movimento = cJSON_GetObjectItem(listaMovimenti, "Movimento")
    if getat(movimento) = %NULL then
        cjson_delete(parsed_json)
        printl "Failed to get Movimento.\n"
        return -1
    end if

    printl cJSON_Print(movimento)

  waitkey

    return 0

end function
FSMaxB commented 7 years ago

Good to hear that it works now.

FSMaxB commented 7 years ago

Note: Accessing the child of payload is necessary because it is an array. In this case accessing the child is enough because it has only one element. Otherwise please use cJSON_ArrayForEach (you can't really port that to Basic though) or cJSON_GetArrayItem

ErosOlmi commented 7 years ago

Thanks a lot for this additional help! Eros

PS: I'm the author of thinBASIC :) http://www.thinbasic.com/