在现代移动应用开发中,JSON已成为数据传输的事实标准。作为Android开发者,掌握高效的JSON解析方式就显得尤为重要。今天,我们将一起探讨三种解析JSON的利器,助你完美驾驭数据通信!


一、 原生org.json解析JSON


1、org.json包使用场景

适合:

  • 简单JSON数据结构
  • 对性能要求不太高的场景
  • 不需要自动映射为对象的场景

2、案例演示

原生org.json库是Java中一个常用的JSON解析工具,它提供了JSONObjectJSONArray类来处理JSON数据。以下是使用org.json库解析JSON数据的完整案例代码演示:


(1)、JSONObject的使用

JSONObject是一个无序的键/值对集合,可以通过键来访问值,也可以添加或替换值。以下是JSONObject的一个使用示例:

public static void jsonObjectTest() {
    JSONObject jsonobj = new JSONObject("{'name':'xiazdong','age':20}");
    String name = jsonobj.getString("name");
    int age = jsonobj.getInt("age");
    System.out.println("name = " + name + ",age = " + age);
}

在这个示例中,我们创建了一个JSONObject实例,并从字符串中初始化它。然后通过getStringgetInt方法获取了JSON对象中的nameage属性,并打印出来。


(2)、 JSONArray的使用

JSONArray是一个有序的序列值,可以通过索引来访问值,也可以添加或修改值。以下是JSONArray的一个使用示例:

public static void jsonArrayTest() {
    JSONArray jsonarray = new JSONArray("[{'name':'xiazdong','age':20},{'name':'xzdong','age':15}]");
    for (int i = 0; i < jsonarray.length(); i++) {
        JSONObject jsonobj = jsonarray.getJSONObject(i);
        String name = jsonobj.getString("name");
        int age = jsonobj.getInt("age");
        System.out.println("name = " + name + ",age = " + age);
    }
}

在这个示例中,我们创建了一个JSONArray实例,并从字符串中初始化它。然后通过循环和getJSONObject方法遍历数组中的每个元素,并获取每个元素的nameage属性。


(3)、嵌套的JSONObject和JSONArray

JSON数据中经常包含嵌套的JSONObjectJSONArray。以下是处理嵌套JSON数据的示例:

// 假设jsonobj是已经初始化的JSONObject对象
String name = jsonobj.getString("name");
int age = jsonobj.getInt("age");
System.out.println("age: " + age);

在这个示例中,我们从嵌套的JSONObject中获取了nameage属性。

(4)、使用JSONStringer构建JSON字符串

JSONStringer类可以用来构建JSON字符串,以下是使用JSONStringer的一个示例:

public static void jsonStringerTest() {
    JSONStringer stringer = new JSONStringer();
    stringer.object().key("name").value("xiazdong").key("age").value(20).endObject();
    System.out.println(stringer);
}

在这个示例中,我们使用JSONStringer创建了一个包含nameage属性的JSON对象,并打印出来。

这些示例展示了如何使用org.json库来解析和构建JSON数据。


二、 使用Google Gson库解析


Google出品的Gson是目前应用最广的JSON库之一。它不仅可以将JSON字符串转换为Java对象,还可以将Java对象转换为JSON字符串。


1、Google Gson适用场景

适合:

  • 中等复杂度的JSON数据
  • 需要自动映射JSON到对象的场景
  • 对开发效率和可读性有较高要求

2、使用案例

以下是使用Gson库解析JSON数据的完整案例代码演示:

步骤 1: 添加Gson库依赖

首先,确保你的项目中已经添加了Gson库的依赖。如果你使用Maven,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version> <!-- 请使用最新的版本号 -->
</dependency>

步骤 2: 创建Java类

创建一个Java类,该类的结构将与要解析的JSON数据相对应。例如,假设我们有以下JSON数据:

{
    "name": "John Doe",
    "age": 30,
    "isEmployed": true,
    "address": {
        "street": "123 Main St",
        "city": "Anytown"
    }
}

我们可以创建以下Java类:

class Address {
    String street;
    String city;

    // 构造函数、getter和setter省略
}

class Person {
    String name;
    int age;
    boolean isEmployed;
    Address address;

    // 构造函数、getter和setter省略

    // 重写toString方法,方便打印对象信息
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isEmployed=" + isEmployed +
                ", address=" + address +
                '}';
    }
}

步骤 3: 使用Gson解析JSON

现在,我们可以使用Gson来解析JSON字符串并将其转换为Java对象:

import com.google.gson.Gson;

public class GsonExample {
    public static void main(String[] args) {
        String json = "{\"name\": \"John Doe\", \"age\": 30, \"isEmployed\": true, " +
                     "\"address\": {\"street\": \"123 Main St\", \"city\": \"Anytown\"}}";

        Gson gson = new Gson();
        Person person = gson.fromJson(json, Person.class);

        System.out.println(person);
    }
}

在这个例子中,我们首先创建了一个Gson实例。然后,使用fromJson方法将JSON字符串转换为Person对象。最后,我们打印出转换后的Person对象。


步骤 4: 运行程序

运行GsonExample类中的main方法,你将看到控制台输出以下内容:

Person{name='John Doe', age=30, isEmployed=true, address=Address{street='123 Main St', city='Anytown'}}

这表明JSON字符串已经被成功解析为Java对象,并且对象的属性已经正确设置。

这个案例演示了如何使用Gson库来解析一个包含嵌套对象的JSON字符串。Gson库非常灵活,可以处理各种复杂的JSON结构,并且可以轻松地将Java对象序列化和反序列化。


三、 Jackson - 功能全面的JSON武器库


如果你需要更高级的JSON处理功能,jackjson-databind就是一个优秀的方案。

1、Jackson 适用场景

  • 高度复杂的JSON数据结构

  • 需要流式API或手动遍历树的场景

  • 对性能和内存占用有极高要求

它的API使用层次分明,功能十分强大,除了数据绑定,Jackson还提供流式API、手动树遍历API等多种方式,无论JSON数据有多复杂,都可以得心应手。


2、使用案例

以下是使用Jackson库解析JSON数据的完整案例代码演示:


步骤 1: 添加Jackson库依赖

首先,确保你的项目中已经添加了Jackson库的依赖。如果你使用Maven,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version> <!-- 请使用最新的版本号 -->
</dependency>

步骤 2: 创建Java类

创建一个Java类,该类的结构将与要解析的JSON数据相对应。例如,假设我们有以下JSON数据:

{
    "name": "John Doe",
    "age": 30,
    "isEmployed": true,
    "address": {
        "street": "123 Main St",
        "city": "Anytown"
    }
}

我们可以创建以下Java类:

import com.fasterxml.jackson.annotation.JsonProperty;

public class Address {
    private String street;
    private String city;

    // 使用@JsonProperty注解可以指定JSON属性名和构造器参数名之间的映射
    @JsonProperty
    public String getStreet() {
        return street;
    }

    @JsonProperty
    public void setStreet(String street) {
        this.street = street;
    }

    @JsonProperty
    public String getCity() {
        return city;
    }

    @JsonProperty
    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "street='" + street + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

public class Person {
    private String name;
    private int age;
    private boolean isEmployed;
    private Address address;

    // 构造函数、getter和setter省略

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isEmployed=" + isEmployed +
                ", address=" + address +
                '}';
    }
}

步骤 3: 使用Jackson解析JSON

现在,我们可以使用Jackson来解析JSON字符串并将其转换为Java对象:

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonExample {
    public static void main(String[] args) throws Exception {
        String json = "{" +
                "  \"name\": \"John Doe\"," +
                "  \"age\": 30," +
                "  \"isEmployed\": true," +
                "  \"address\": {" +
                "    \"street\": \"123 Main St\"," +
                "    \"city\": \"Anytown\"" +
                "  }" +
                "}";
        
        ObjectMapper objectMapper = new ObjectMapper();
        Person person = objectMapper.readValue(json, Person.class);

        System.out.println(person);
    }
}

在这个例子中,我们首先创建了一个ObjectMapper实例。然后,使用readValue方法将JSON字符串转换为Person对象。最后,我们打印出转换后的Person对象。


步骤 4: 运行程序

运行JacksonExample类中的main方法,你将看到控制台输出以下内容:

Person{name='John Doe', age=30, isEmployed=true, address=Address{street='123 Main St', city='Anytown'}}

这表明JSON字符串已经被成功解析为Java对象,并且对象的属性已经正确设置。

这个案例演示了如何使用Jackson库来解析一个包含嵌套对象的JSON字符串。


四、三种方案的优缺点对比


1、org.json包

优点:

  • Android内置,无需引入外部库
  • 实现简单直接

缺点:

  • 缺乏类型安全性,容易引入bug
  • 对复杂JSON数据解析效率低下

总之,这种方式虽然简单直接,但缺乏类型安全性,编码时容易出错。对于复杂JSON也显得有些笨重。


2、Google Gson

优点:

  • 自动映射对象,使用简洁
  • 性能良好,运行高效
  • 不会产生大量临时对象

缺点:

  • 对一些复杂的数据结构可能无法完美映射

  • 无法精细控制序列化/反序列化过程

Gson自动将JSON数据映射到指定的Java对象,无需手动解析。它的性能也很不错,总的来说是一个非常棒的选择。


3、Jackson

优点:

  • 功能强大,可扩展性好
  • 流式API性能卓越
  • 对数据绑定有极高的自定义能力

缺点:

  • 相对更重,有一定学习曲线
  • 对象绑定时可能产生较多临时对象

Jackson库提供了丰富的功能,包括数据绑定、流式处理以及树模型处理,可以满足不同的JSON处理需求。当然,相较于Gson,它的性能和编码复杂度也会相对偏高一些。


五、最佳实践和注意事项


1、选择适合的方案

根据你的具体JSON数据复杂度和场景需求,选择最合适的解析方案,避免过度设计。

2、注意内存友好性

解析JSON时要格外小心,尽量避免一次加载所有数据到内存中。可以使用流式API或者分段加载的方式。

3、使用线程池

JSON解析可能会造成UI线程阻塞,建议使用线程池或异步任务执行解析操作。

4、实现对象重用

一些库在解析时会产生大量临时对象,要注意对象重用以节省内存。

5、处理解析异常

一定要谨记处理解析过程中可能出现的各种异常,并作出恰当响应。


六、总结


这三种解析JSON的方案各有特点,我们可以根据具体需求和项目复杂程度权衡选择。而在我看来,Google Gson则是大多数应用的不二之选,它Strike了简洁和性能之间最好的平衡。


讨论到这里,你是否也有自己的看法和经验?欢迎在评论区继续交流探讨,分享你在JSON解析这条路上的点点心得。


GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:16 天前 )
960b763e 3 个月前
8c391e04 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐