Android应用开发遇JSON异常:org.json.JSONException: No value for data
嘿,我帮你搞定这个问题!你遇到的org.json.JSONException: No value for data主要是因为JSON格式错误,再加上代码里的一些小问题,咱们一步步来解决:
首先修复JSON格式错误(这是异常的核心原因)
你的JSON文件有两处语法问题,导致解析器无法识别"data"键:
- 所有键名必须用双引号包裹,比如
"data"而不是data; - 第二个对象里的
"pronunciation:"b"引号配对错误,应该是"pronunciation":"b"。
修正后的JSON:
{ "data": [ { "character": "a", "pronunciation": "a" }, { "character": "b", "pronunciation": "b" } ] }
然后优化MainActivity代码,实现切换字符功能
原来的代码有几个问题:比如固定长度数组容易越界、onCreate里提前访问未初始化的数组、没有切换字符的逻辑。这里给你调整后的代码,注释里有详细说明:
package com.example.pirama3.pirama3; import android.content.res.Resources; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class MainActivity extends AppCompatActivity { // 用动态List存储字符,比固定数组更灵活,避免越界 private List<String> characterList = new ArrayList<>(); // 记录当前显示的字符索引,实现切换功能 private int currentIndex = 0; private TextView characterTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 提前初始化TextView,避免重复查找 characterTextView = findViewById(R.id.abc); } // 按钮点击事件:第一次点击加载数据,之后点击切换字符 public void loadGrades(View view) { if (characterList.isEmpty()) { // 数据未加载,先加载JSON loadAndParseJson(); } else { // 数据已加载,切换到下一个字符 showNextCharacter(); } } // 加载raw目录下的JSON文件并解析 private void loadAndParseJson() { Resources res = getResources(); InputStream is = res.openRawResource(R.raw.test02); Scanner scanner = new Scanner(is); StringBuilder jsonBuilder = new StringBuilder(); while (scanner.hasNextLine()) { jsonBuilder.append(scanner.nextLine()); } try { JSONObject rootObj = new JSONObject(jsonBuilder.toString()); // 用optJSONArray替代getJSONArray,避免找不到键时抛出异常 JSONArray dataArray = rootObj.optJSONArray("data"); if (dataArray != null) { for (int i = 0; i < dataArray.length(); i++) { JSONObject charObj = dataArray.getJSONObject(i); // 用optString获取字符,找不到时返回空字符串 String character = charObj.optString("character", ""); if (!character.isEmpty()) { characterList.add(character); Log.d("Loaded Character", character); } } // 加载完成后显示第一个字符 characterTextView.setText(characterList.get(currentIndex)); } else { Log.e("JSON Error", "找不到data数组"); characterTextView.setText("数据加载失败"); } } catch (JSONException e) { e.printStackTrace(); characterTextView.setText("JSON解析出错"); } } // 切换到下一个字符,循环显示 private void showNextCharacter() { if (characterList.isEmpty()) return; // 用取模实现循环,到最后一个字符后回到第一个 currentIndex = (currentIndex + 1) % characterList.size(); characterTextView.setText(characterList.get(currentIndex)); } }
代码调整说明
- JSON解析优化:用
optJSONArray和optString替代get方法,减少不必要的异常,同时添加错误提示; - 切换逻辑实现:新增
currentIndex计数器,点击按钮时递增并取模,实现循环切换字符; - 避免空指针:提前初始化TextView,数据加载完成后再显示内容,避免访问未初始化的数组;
- 动态数据存储:用
ArrayList代替固定长度数组,适配JSON中不同数量的字符数据。
这样调整后,不仅能解决你遇到的JSON异常,还能完美实现点击按钮切换字符的功能啦!
内容的提问来源于stack exchange,提问作者Jackson Smith




