Как получить значение JSON с помощью класса TJSONObject в C Builder?

#json #c builder

#json #c builder

Вопрос:

Я не смог получить определенное значение JSON, используя TJSONObject , я получаю ошибку Access violation at address xxxxxxxxx .

У меня проблема с получением желаемого значения с использованием его имени ключа из файла JSON, в настоящее время я использую TRESTClient , TRESTRequest , TRESTResponse для получения данных JSON из Интернета, я использовал тот же URL-адрес JSON с помощью Javascript и работает нормально, но в C Builder этого не происходит, он просто показывает мне ошибку Access violation at address xxxxxxxxx blablabla , чтопроисходит, когда я пытаюсь получить определенное значение JSON, используя его имя, например, например: "name": "sparky" , но когда я получаю полный файл JSON, он завершается успешно без ошибок.

Код:

 TJSONObject *JSONObject = new TJSONObject();

__try
{
    RESTClient1->BaseURL = "https://learnwebcode.github.io/json-example/animals-1.json";
    RESTRequest1->Execute();
    JSONObject = dynamic_cast<TJSONObject*>( TJSONObject::ParseJSONValue(RESTResponse1->JSONText) ) ;
    TJSONPair *pair = JSONObject->Get("name");
    Memo1->Text = pair->JsonValue->ToString();

}
__finally
{
    delete JSONObject;
}
  

ОБНОВЛЕНИЕ: это файл JSON, из которого я хочу получить значения.

 [
    {
    "name":"Meowsy",
    "species":"cat",
    "foods":
    {
      "likes":
      [
        "tuna",
        "catnip"
      ]
,
      "dislikes":
      [
        "ham",
        "zucchini"
      ]
    }
  }
,

  {
    "name":"Barky",
    "species":"dog",
    "foods":
    {
      "likes":
      [
        "bones",
        "carrots"
      ]
,
      "dislikes":
      [
        "tuna"
      ]
    }
  }
,

  {
    "name":"Purrpaws",
    "species":"cat",
    "foods":
    {
      "likes":
      [
        "mice"
      ]
,
      "dislikes":
      [
        "cookies"
      ]
    }
  }
]
  

Комментарии:

1. ParseJSONValue возвращает нулевой объект, если синтаксический анализ завершается неудачей. Вы не проверяете, является ли JSONObject допустимым (не NULL), прежде чем использовать его. Отладьте свой код и проверьте, что содержит RESTResponse->JSONText и имеет ли значение JSONObject значение NULL:

2. FWIW, вы создаете утечку памяти. Вы создаете JSONObject, но перезаписываете его ссылку результатом ParseJSONValue . Это означает, что исходное значение больше не обновляется, поэтому недоступно и больше не может быть удалено. Итак, у вас утечка.

3. JSONObject допустим, я уже проверил это, и он возвращает строку json TMemo , но проблема в том, что она не дает мне определенного значения, как я объяснил в своем вопросе, кстати, я взял приведенный выше код из qiita.com/7of9/items/522ebfd25328df5c7777

4. Итак, каково решение

5. Итак, я предполагаю, что пара недействительна? Какой текст в JSONObject? Если оно не слишком большое, опубликуйте его тоже. И позаботьтесь об утечке памяти.

Ответ №1:

Показанный вами JSON представляет собой МАССИВ ОБЪЕКТОВ, а не ОДИН ОБЪЕКТ, как предполагает ваш код. Таким TJSONObject::ParseJSONValue() TJSONArray образом, вместо a будет возвращено a TJSONObject , и поэтому ваше утверждение в комментариях о том, что «JSONObject является действительным», не может быть истинным, поскольку dynamic_cast<TJSONObject*> оно завершится ошибкой и вернет NULL, который ваш код не проверяет. Вы не показали ПОЛНОЕ сообщение об ошибке, но если оно говорит «чтение адреса 00000000», это хороший признак того, что осуществляется доступ к нулевому указателю.

Кроме того, TJSONObject::Get() устарело. Чтобы получить значение по имени, используйте TJSONObject::GetValue() вместо.

Кроме того, TRESTResponse можно проанализировать JSON для вас, если вы используете TRESTResponse::JSONValue свойство вместо TRESTResponse::JSONText свойства.

Кроме того, вы пропускаете TJSONObject то, что выделяете, если ваш код скомпилирован с использованием одного из компиляторов C , не основанных на ARC.

С учетом сказанного, попробуйте следующее:

 RESTClient1->BaseURL = "https://learnwebcode.github.io/json-example/animals-1.json";
RESTRequest1->Execute();

Memo1->Clear();

TJSONValue *JSONValue = RESTResponse1->JSONValue;
if (JSONValue)
{
    if (TJSONArray *JSONArray = dynamic_cast<TJSONArray*>(JSONValue))
    {
        for (int i = 0; i < JSONArray->Count;   i)
        {
            TJSONObject *JSONObject = dynamic_cast<TJSONObject*>(JSONArray->Items[i]);
            if (JSONObject)
            {
                TJSONValue *JSONObjectName = JSONObject->GetValue("name");
                if (JSONObjectName)
                    Memo1->Lines->Add(JSONObjectName->Value());
            }
        }
    }
    else if (TJSONObject JSONObject = dynamic_cast<TJSONObject*>(JSONValue))
    {
        TJSONValue *JSONObjectName = JSONObject->GetValue("name");
        if (JSONObjectName)
            Memo1->Text = JSONObjectName->Value();
    }
    else
    {
        Memo1->Text = "Ignoring unsupported JSON value type";
    }
}
else
{
    Memo1->Text = "JSON not parsed";
}
  

Комментарии:

1. Я знаю, что я все еще новичок в программировании на C , часто такие мелочи сбивают меня с толку на моем уровне программирования, но я изучаю новые вещи по пути, и большое вам спасибо за вашу помощь.

2. «Кроме того, показанный вами код даже не должен компилироваться, потому что TJSONObject::Get() принимает числовой индекс в качестве входных данных, а не имя ключа». Существует перегрузка, которая принимает имя, но оно устарело. Однако он должен компилироваться.

3. @RudyVelthuis, по-видимому, обе перегрузки TJSONObject::Get() устарели. Но замечание о компиляции кода. Я обновил свой ответ