You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON数组首字母缺失及HTTP Get请求数组解析技术问询

问题1:JSON数组存在首字母缺失的情况该如何处理?

咱们先拆解这个问题,通常分两种常见场景,对应不同的解决办法:

场景1:JSON语法本身不合法(数组标记缺失)

如果是后端返回的JSON字符串本身有语法错误——比如本该是标准数组格式[{...}, {...}],但开头少了[,或者结尾少了],导致无法被解析器识别为数组。这种情况优先让后端修复数据源,但如果暂时没法改后端,咱们可以手动修正字符串:

String rawJson = "你收到的有问题的JSON";
// 补全开头的[
if (!rawJson.trim().startsWith("[")) {
    rawJson = "[" + rawJson;
}
// 补全结尾的]
if (!rawJson.trim().endsWith("]")) {
    rawJson += "]";
}
// 现在可以用这个修正后的字符串去解析了

场景2:字段键名首字母与实体类属性不匹配

另一种情况是JSON里的字段首字母是小写(比如category_id),但你的Java实体类属性用了驼峰式首字母大写(比如categoryId),导致解析时字段映射失败。这种情况用序列化注解就能搞定,比如Gson的@SerializedName:

public class Category {
    @SerializedName("category_id") // 对应JSON里的字段名
    private String categoryId; // 你的实体类属性名
    
    @SerializedName("category_name")
    private String categoryName;
    
    @SerializedName("parent_id")
    private int parentId;
    
    // 别忘了空构造方法、getter和setter
}

这样解析器就能正确把JSON字段映射到实体类属性上了。


问题2:Android中解析HTTP GET请求返回的JSON数组

我基于你给的初始代码,一步步帮你补全实现,注意绝对不能在主线程发网络请求,所以咱们用基础的AsyncTask(新手友好),最后再给你推荐现代Android开发常用的Retrofit方案。

第一步:先配置基础权限和依赖

  1. 添加网络权限:在AndroidManifest.xml里加一行:
<uses-permission android:name="android.permission.INTERNET" />

如果你的APP目标是Android 9+,还要处理明文HTTP的问题:要么接口用HTTPS,要么在res/xml下创建network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

然后在Manifest的application标签里引用:

<application
    ...
    android:networkSecurityConfig="@xml/network_security_config">
  1. 添加Gson依赖:在模块级build.gradle的dependencies里加:
implementation 'com.google.code.gson:gson:2.10.1'

第二步:创建实体类匹配JSON结构

先写一个Category.java类,对应你收到的JSON字段:

public class Category {
    private String category_id;
    private String category_name;
    private int parent_id;

    // 空构造方法必须要有,Gson解析需要
    public Category() {}

    // Getter和Setter方法
    public String getCategory_id() { return category_id; }
    public void setCategory_id(String category_id) { this.category_id = category_id; }
    public String getCategory_name() { return category_name; }
    public void setCategory_name(String category_name) { this.category_name = category_name; }
    public int getParent_id() { return parent_id; }
    public void setParent_id(int parent_id) { this.parent_id = parent_id; }
}

如果觉得下划线字段名看着别扭,就用问题1里的@SerializedName改成驼峰式就行。

第三步:补全Welcome Activity的代码

把你给的初始代码补全,加上网络请求和解析逻辑:

public class Welcome extends Activity {
    Button btnLogout;
    TextView tvWelcome; // 假设你有个TextView显示欢迎语,记得在布局里加

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        // 初始化控件
        btnLogout = findViewById(R.id.btn_logout);
        tvWelcome = findViewById(R.id.tv_welcome);

        // 显示欢迎语
        String username = getIntent().getStringExtra("Username");
        if (username != null) {
            tvWelcome.setText("Welcome, " + username);
        }

        // 发起网络请求获取并解析分类数组
        new FetchCategoriesTask().execute();

        // 退出按钮逻辑
        btnLogout.setOnClickListener(v -> {
            Intent loginIntent = new Intent(Welcome.this, LoginActivity.class);
            startActivity(loginIntent);
            finish();
        });
    }

    // 用AsyncTask在后台处理网络请求,避免阻塞主线程
    private class FetchCategoriesTask extends AsyncTask<Void, Void, List<Category>> {

        @Override
        protected List<Category> doInBackground(Void... voids) {
            List<Category> categoryList = new ArrayList<>();
            // 替换成你的实际API地址
            String apiUrl = "https://your-api-domain.com/get-categories";

            try {
                URL url = new URL(apiUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(5000); // 5秒超时
                connection.setReadTimeout(5000);

                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder responseBuilder = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseBuilder.append(line);
                }
                reader.close();
                connection.disconnect();

                // 用Gson解析JSON数组
                Gson gson = new Gson();
                Category[] categories = gson.fromJson(responseBuilder.toString(), Category[].class);
                if (categories != null) {
                    categoryList = Arrays.asList(categories);
                }

            } catch (IOException e) {
                e.printStackTrace(); // 实际开发中要处理异常,比如提示用户网络错误
            }

            return categoryList;
        }

        @Override
        protected void onPostExecute(List<Category> categories) {
            super.onPostExecute(categories);
            // 这里回到主线程,处理解析后的数组,比如显示到RecyclerView或打印日志
            if (categories != null && !categories.isEmpty()) {
                for (Category cat : categories) {
                    Log.d("CategoryInfo", "ID: " + cat.getCategory_id() + " | Name: " + cat.getCategory_name());
                }
            } else {
                Log.d("CategoryInfo", "未获取到分类数据");
            }
        }
    }
}

更推荐的现代方案:Retrofit + Coroutines

如果是新开发的项目,更推荐用Retrofit,代码更简洁且维护性更好:

  1. 添加依赖:在build.gradle里加:
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
  1. 创建API接口:
public interface CategoryApi {
    @GET("get-categories") // 替换成你的接口路径
    Call<List<Category>> getCategories();
}
  1. 在Activity里发起请求:
// 在onCreate方法里
// 初始化Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://your-api-domain.com/") // 替换成你的API基础地址
        .addConverterFactory(GsonConverterFactory.create())
        .build();

CategoryApi categoryApi = retrofit.create(CategoryApi.class);

// 用Coroutines在后台发起请求
CoroutineScope(Dispatchers.IO).launch {
    try {
        Response<List<Category>> response = categoryApi.getCategories().execute();
        if (response.isSuccessful()) {
            List<Category> categories = response.body();
            // 切回主线程更新UI
            runOnUiThread(() -> {
                if (categories != null) {
                    // 处理数据,比如显示到列表
                }
            });
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者techker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:40:48