Я не смог получить определенное значение 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"
]
}
}
]
FWIW, вы создаете утечку памяти. Вы создаете JSONObject, но перезаписываете его ссылку результатом ParseJSONValue. Это означает, что исходное значение больше не используется, поэтому оно недоступно и больше не может быть удалено. Итак, у вас есть утечка.
JSONObject действителен, я уже проверил это, и он возвращает строку json в TMemo
, но проблема в том, что он не дает мне определенного значения, как я объяснил в своем вопросе, кстати, я взял приведенный выше код из qiita.com/7of9/items/522ebfd25328df5c7777
Итак, какое решение
Я так понимаю пара недействительна? Что такое текст в JSONObject? Если он не слишком большой, опубликуйте его тоже. И позаботьтесь об утечке памяти.
FWIW "JSONObject действителен, я уже проверил это". Было бы неплохо, если бы вы указали это в вопросе. Пожалуйста, предоставьте всю необходимую информацию, чтобы людям не приходилось строить догадки или спрашивать.
См. ОБНОВИТЬ выше
Я посмотрю, когда у меня будет время, позже.
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++, часто эти мелочи сбивают меня с толку на моем уровне программирования, но по пути я изучаю новые вещи, и большое спасибо за вашу помощь.
«Кроме того, код, который вы показали, даже не должен компилироваться, потому что TJSONObject::Get() принимает в качестве входных данных числовой индекс, а не имя ключа». Существует перегрузка, которая принимает имя, но она устарела. Однако он должен скомпилироваться.
@RudyVelthuis, по-видимому, обе перегрузки TJSONObject::Get()
устарели. Но речь идет о компиляции кода. я обновил свой ответ
ParseJSONValue возвращает объект NULL в случае сбоя синтаксического анализа. Вы не проверяете, является ли JSONObject действительным (не NULL), прежде чем использовать его. Отладьте свой код и проверьте, что содержит RESTResponse->JSONText, и если JSONObject имеет значение NULL: