在 Android 开发中,JSON(JavaScript Object Notation)是网络请求中最常见的数据格式,用于从服务器获取数据或解析本地 JSON 文件。Android 提供了多种方式解析 JSON 数据,包括原生的 JSONObjectJSONArray,以及第三方库如 GsonMoshi以下是 Android JSON 数据解析的详细学习指南,涵盖解析方法、代码示例、结合 HTTP 请求、注意事项和实践建议。


一、JSON 解析方法概述

Android 支持以下主要 JSON 解析方式:

  1. JSONObject 和 JSONArray

    • 特点:Android 原生提供的 JSON 解析类,基于 org.json 包。
    • 优点:无需额外依赖,简单易用。
    • 缺点:手动解析代码冗长,易出错,不支持复杂对象映射。
    • 适用场景:简单 JSON 数据解析,快速原型开发。
  2. Gson

    • 特点:Google 提供的开源库,将 JSON 自动映射到 Java/Kotlin 对象。
    • 优点:代码简洁,支持复杂对象、自定义序列化/反序列化。
    • 缺点:需添加依赖,性能略低于 Moshi。
    • 适用场景:大多数 Android 项目,适合复杂 JSON 结构。
  3. Moshi

    • 特点:Square 提供的轻量级 JSON 解析库,类似 Gson 但更现代。
    • 优点:性能高,支持 Kotlin(通过反射或代码生成),类型安全。
    • 缺点:需添加依赖,学习曲线稍陡。
    • 适用场景:Kotlin 项目,追求高性能或类型安全的场景。
  4. Jackson(较少使用):

    • 特点:功能强大的 JSON 解析库,支持流式解析。
    • 优点:适合大型 JSON 文件或复杂场景。
    • 缺点:配置复杂,依赖较重。
    • 适用场景:特殊需求或跨平台项目。

二、准备工作

  1. 网络权限(如从网络获取 JSON 数据):
    AndroidManifest.xml 中添加:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
  2. 示例 JSON 数据
    假设以下 JSON 数据用于解析:

    {
        "users": [
            {
                "id": 1,
                "name": "Alice",
                "age": 25
            },
            {
                "id": 2,
                "name": "Bob",
                "age": 30
            }
        ]
    }
    
  3. 数据来源

    • 网络请求:通过 HttpURLConnection、OkHttp 或 Retrofit 获取 JSON 数据。
    • 本地文件:将 JSON 文件放入 res/rawassets 目录。
    • 字符串:直接解析 JSON 字符串。
  4. 添加依赖(Gson 或 Moshi):
    build.gradle(app 模块)中添加:

    // Gson
    implementation 'com.google.code.gson:gson:2.10.1'
    // Moshi
    implementation 'com.squareup.moshi:moshi:1.15.0'
    // Moshi Kotlin 支持(可选)
    implementation 'com.squareup.moshi:moshi-kotlin:1.15.0'
    

三、JSON 解析方法详解与代码示例

以下是使用 JSONObjectGsonMoshi 解析上述 JSON 的代码示例。

1. 使用 JSONObject 和 JSONArray

JSONObjectJSONArray 是 Android 原生的 JSON 解析工具。

  • 代码示例

    import org.json.JSONArray;
    import org.json.JSONObject;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    public class JsonParser {
        public static class User {
            String id, name, age;
    
            @Override
            public String toString() {
                return "User{id='" + id + "', name='" + name + "', age='" + age + "'}";
            }
        }
    
        public static List<User> parseJsonWithJsonObject(String jsonString) throws Exception {
            List<User> users = new ArrayList<>();
            JSONObject jsonObject = new JSONObject(jsonString);
            JSONArray usersArray = jsonObject.getJSONArray("users");
    
            for (int i = 0; i < usersArray.length(); i++) {
                JSONObject userObject = usersArray.getJSONObject(i);
                User user = new User();
                user.id = userObject.getString("id");
                user.name = userObject.getString("name");
                user.age = userObject.getString("age");
                users.add(user);
            }
            return users;
        }
    }
    
  • 使用示例(从网络获取 JSON):

    new Thread(() -> {
        try {
            URL url = new URL("https://api.example.com/users.json");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
    
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = conn.getInputStream();
                String jsonString = new BufferedReader(new InputStreamReader(inputStream))
                        .lines().collect(Collectors.joining("\n"));
                inputStream.close();
                List<JsonParser.User> users = JsonParser.parseJsonWithJsonObject(jsonString);
                runOnUiThread(() -> {
                    for (JsonParser.User user : users) {
                        Log.d("JsonObject", user.toString());
                    }
                });
            }
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
    
2. 使用 Gson

Gson 自动将 JSON 映射到 Java/Kotlin 对象,代码简洁。

  • 定义模型类

    public class User {
        @SerializedName("id")
        String id;
        @SerializedName("name")
        String name;
        @SerializedName("age")
        String age;
    
        @Override
        public String toString() {
            return "User{id='" + id + "', name='" + name + "', age='" + age + "'}";
        }
    }
    
    public class UserResponse {
        @SerializedName("users")
        List<User> users;
    }
    
  • 解析代码

    import com.google.gson.Gson;
    import java.io.InputStream;
    import java.util.List;
    
    public class GsonParser {
        public static List<User> parseJsonWithGson(String jsonString) {
            Gson gson = new Gson();
            UserResponse response = gson.fromJson(jsonString, UserResponse.class);
            return response.users;
        }
    }
    
  • 使用示例(从本地 assets 文件解析):

    new Thread(() -> {
        try {
            InputStream inputStream = getAssets().open("users.json");
            String jsonString = new BufferedReader(new InputStreamReader(inputStream))
                    .lines().collect(Collectors.joining("\n"));
            inputStream.close();
            List<User> users = GsonParser.parseJsonWithGson(jsonString);
            runOnUiThread(() -> {
                for (User user : users) {
                    Log.d("Gson", user.toString());
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
    
3. 使用 Moshi

Moshi 是现代化的 JSON 解析库,特别适合 Kotlin 项目。

  • 定义模型类(Kotlin):

    data class User(
        @Json(name = "id") val id: String,
        @Json(name = "name") val name: String,
        @Json(name = "age") val age: String
    )
    
    data class UserResponse(
        @Json(name = "users") val users: List<User>
    )
    
  • 解析代码(Kotlin):

    import com.squareup.moshi.Moshi
    import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
    import java.io.InputStream
    
    object MoshiParser {
        fun parseJsonWithMoshi(jsonString: String): List<User> {
            val moshi = Moshi.Builder()
                .add(KotlinJsonAdapterFactory())
                .build()
            val adapter = moshi.adapter(UserResponse::class.java)
            return adapter.fromJson(jsonString)?.users ?: emptyList()
        }
    }
    
  • 使用示例(从网络获取 JSON,Kotlin 协程):

    suspend fun fetchAndParseJson(urlString: String): List<User> = withContext(Dispatchers.IO) {
        val url = URL(urlString)
        val conn = url.openConnection() as HttpURLConnection
        try {
            conn.requestMethod = "GET"
            conn.setRequestProperty("Accept", "application/json")
            if (conn.responseCode == HttpURLConnection.HTTP_OK) {
                val jsonString = conn.inputStream.bufferedReader().use { it.readText() }
                MoshiParser.parseJsonWithMoshi(jsonString)
            } else {
                emptyList()
            }
        } finally {
            conn.disconnect()
        }
    }
    
    // 调用
    lifecycleScope.launch {
        try {
            val users = fetchAndParseJson("https://api.example.com/users.json")
            users.forEach { Log.d("Moshi", it.toString()) }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    

四、结合 HttpURLConnection 获取 JSON 数据

以下是使用 HttpURLConnection 获取 JSON 数据并用 Gson 解析的完整示例:

public void fetchAndParseJson(String urlString) {
    new Thread(() -> {
        HttpURLConnection conn = null;
        try {
            // 1. 获取 JSON 数据
            URL url = new URL(urlString);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setRequestProperty("Accept", "application/json");

            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                String jsonString = new BufferedReader(new InputStreamReader(conn.getInputStream()))
                        .lines().collect(Collectors.joining("\n"));
                // 2. 解析 JSON
                List<User> users = GsonParser.parseJsonWithGson(jsonString);
                // 3. 更新 UI
                runOnUiThread(() -> {
                    for (User user : users) {
                        Log.d("Gson", user.toString());
                    }
                });
            } else {
                Log.e("Error", "Response Code: " + conn.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }).start();
}

五、解析方法对比

解析方法 依赖 代码复杂性 性能 适用场景
JSONObject 中等 简单 JSON,快速原型开发
Gson 需要依赖 复杂 JSON,Java/Kotlin 项目
Moshi 需要依赖 更高 Kotlin 项目,追求性能
Jackson 需要依赖 大型 JSON 或跨平台项目
  • 推荐:Android 项目优先使用 Gson(Java/Kotlin)或 Moshi(Kotlin),简单场景可使用 JSONObject
  • 选择依据
    • 简单 JSON:使用 JSONObject
    • 复杂对象映射:使用 Gson 或 Moshi。
    • Kotlin 项目:优先 Moshi。

六、注意事项

  1. 异步处理
    • JSON 解析通常与网络请求结合,必须在子线程执行,避免 NetworkOnMainThreadException
    • 使用 Thread、AsyncTask(已废弃)或 Kotlin 协程。
  2. 错误处理
    • 处理 JSONExceptionJSONObject)、JsonParseException(Gson)或 IOException(Moshi)。
    • 检查 HTTP 状态码和 JSON 格式是否正确。
    • 示例:
      try {
          JSONObject jsonObject = new JSONObject(jsonString);
      } catch (JSONException e) {
          Log.e("Error", "Invalid JSON: " + e.getMessage());
      }
      
  3. 资源释放
    • 关闭 InputStreamHttpURLConnection
    • 示例:
      inputStream.close();
      conn.disconnect();
      
  4. 性能优化
    • 使用 Gson 或 Moshi 映射对象,减少手动解析代码。
    • 缓存解析结果,减少重复解析。
    • 对于大型 JSON,考虑流式解析(如 Jackson 的 JsonParser)。
  5. 安全性
    • 验证 JSON 数据来源,避免解析恶意数据。
    • 使用 @SerializedName(Gson)或 @Json(Moshi)确保字段映射正确。
  6. 编码处理
    • 确保 JSON 数据编码为 UTF-8:
      String jsonString = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))
              .lines().collect(Collectors.joining("\n"));
      

七、学习建议与实践

  1. 学习路径
    • 了解 JSON 结构(对象、数组、嵌套)。
    • 掌握 JSONObjectJSONArray 的基本使用。
    • 学习 Gson 自动映射对象,处理复杂 JSON。
    • 在 Kotlin 项目中使用 Moshi,结合协程。
    • 结合 HttpURLConnection 或 OkHttp 获取 JSON 数据。
  2. 实践项目
    • 简单项目:调用公开 API(如 OpenWeatherMap),解析天气 JSON 数据。
    • 进阶项目:实现用户列表应用,解析嵌套 JSON,显示在 RecyclerView。
    • 本地文件:将 JSON 文件放入 res/rawassets,练习解析。
  3. 调试工具
    • 使用 Postman 测试 JSON API,验证响应。
    • 使用 Charles 抓包,分析 JSON 数据。
    • 使用 Android Studio 的 Logcat 查看解析结果。
  4. 推荐资源
    • Gson 文档:https://github.com/google/gson
    • Moshi 文档:https://github.com/square/moshi
    • Android 官方文档:https://developer.android.com/reference/org/json/JSONObject
    • 实践 API:https://api.github.com/users 或 https://openweathermap.org/api

八、Kotlin 协程与 Retrofit 示例

结合 Retrofit 和 Moshi,异步解析 JSON(Kotlin):

  • Retrofit 接口

    interface ApiService {
        @GET("users.json")
        suspend fun getUsers(): UserResponse
    }
    
  • 配置 Retrofit

    val moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .build()
    val retrofit = Retrofit.Builder()
        .baseUrl("https://api.example.com/")
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .build()
    val apiService = retrofit.create(ApiService::class.java)
    
  • 调用和解析

    lifecycleScope.launch {
        try {
            val users = apiService.getUsers().users
            users.forEach { Log.d("Moshi", it.toString()) }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    

九、总结

  • 解析方法
    • JSONObject/JSONArray:原生,适合简单 JSON。
    • Gson:自动映射,适合复杂 JSON,Java/Kotlin 通用。
    • Moshi:轻量高效,适合 Kotlin 项目。
  • 结合网络:使用 HttpURLConnection、OkHttp 或 Retrofit 获取 JSON 数据,异步解析。
  • 注意事项:异步处理、错误处理、资源释放、编码一致。
  • 推荐:优先使用 Gson 或 Moshi,新项目结合 Retrofit 和协程。
  • 实践:调用 JSON API 或解析本地文件,结合调试工具验证。

如果需要更详细的代码示例(如解析复杂嵌套 JSON、自定义 Gson 序列化)、第三方库对比或特定场景的讲解,请告诉我!

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐