#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/522ebfd25328df5c77774. Итак, каково решение
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()
устарели. Но замечание о компиляции кода. Я обновил свой ответ