Как получить значение JSON с помощью класса TJSONObject в 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, используя его имя, например, для EX: "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"
      ]
    }
  }
]

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

Rudy Velthuis 08.04.2019 10:56

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

Rudy Velthuis 08.04.2019 11:01

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

Abdennour 08.04.2019 11:05

Итак, какое решение

Abdennour 08.04.2019 11:09

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

Rudy Velthuis 08.04.2019 11:52

FWIW "JSONObject действителен, я уже проверил это". Было бы неплохо, если бы вы указали это в вопросе. Пожалуйста, предоставьте всю необходимую информацию, чтобы людям не приходилось строить догадки или спрашивать.

Rudy Velthuis 08.04.2019 11:54

См. ОБНОВИТЬ выше

Abdennour 08.04.2019 12:08

Я посмотрю, когда у меня будет время, позже.

Rudy Velthuis 08.04.2019 17:17
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
8
2 608
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

JSON, который вы показали, представляет собой МАССИВ ОБЪЕКТОВ, а не ОДИН ОБЪЕКТ, как предполагает ваш код. Таким образом, TJSONObject::ParseJSONValue() вернет TJSONArray вместо 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";
}

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

Abdennour 09.04.2019 08:23

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

Rudy Velthuis 10.04.2019 11:20

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

Remy Lebeau 10.04.2019 18:01

Другие вопросы по теме