前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >走进Java接口测试之fastjson指南

走进Java接口测试之fastjson指南

作者头像
高楼Zee
发布2019-07-17 16:05:15
1.4K0
发布2019-07-17 16:05:15
举报
文章被收录于专栏:7DGroup
引言

在上文 走进Java接口测试之理解JSON和XML基础 我们介绍了 JSON 的基础知识,本文我们深入研究阿里巴巴的开源 JSON 解析库 fastjson。

什么是fastjson?

fastjson 是阿里巴巴的开源 JSON 解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到JavaBean。

截止2019/2/1:

  • Github Stars: 16434
  • Github Forks: 4661

GitHub:https://github.com/alibaba/fastjson/

fastjson的特点

速度快

fastjson 相对其他 JSON 库的特点是快,从 2011 年 fastjson 发布1.1.x版本之后,其性能从未被其他 Java 实现的 JSON 库超越。

使用广泛

fastjson 在阿里巴巴大规模使用,在数万台服务器上部署,fastjson 在业界被广泛接受。在 2012 年被开源中国评选为最受欢迎的国产开源软件之一。

测试完备

fastjson 有非常多的 testcase,在1.2.11版本中,testcase 超过3321个。每次发布都会进行回归测试,保证质量稳定。

使用简单

fastjson 的 API 十分简洁。

代码语言:javascript
复制
String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化

功能完备

支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。

fastjson使用

Maven配置

为了开始使用FastJson,我们首先需要将它添加到我们的 pom.xml

代码语言:javascript
复制
<!--引入效率插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--引入FastJson包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <!--引入testng测试框架-->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
        </dependency>

将Java对象转换为JSON格式

让我们定义以下Person Java bean

代码语言:javascript
复制
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {

       @JSONField(name = "AGE")
    private int age;

    @JSONField(name = "FULL NAME")
    private String fullName;

    @JSONField(name = "DATE OF BIRTH")
    private Date dateOfBirth;
}

我们可以使用 JSON.toJSONString() 将 Java 对象转换为 JSON 字符串

代码语言:javascript
复制
private List<Person> listOfPersons;

    @BeforeTest
    public void setUp() {
        listOfPersons = new ArrayList<Person>();
        // 获取当前时间,取得一个Calendar的实例
        Calendar calendar = Calendar.getInstance();
        // 设置日历
        calendar.set(2019, 01, 31);
        // 实例化Java对象
        listOfPersons.add(new Person(15, "John Doe", calendar.getTime()));
        listOfPersons.add(new Person(20, "Janette Doe", calendar.getTime()));
    }

    @Test(description = "将Java对象转换为JSON格式")
    public void whenJavaList_thanConvertToJsonCorrect() {

        // 将Java对象转换为JSON字符串
        String personJsonFormat = JSON.toJSONString(listOfPersons);
}

这是结果:

代码语言:javascript
复制
[  
    {  
        "AGE":15,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"John Doe"
    },
    {  
        "AGE":20,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"Janette Doe"
    }
]

我们还可以进一步开始自定义输出并控制排序,日期格式或序列化标志等内容。 例如 - 让我们更新 bean 并添加几个字段:

代码语言:javascript
复制
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    // 忽略序列化和反序列化
    @JSONField(name = "AGE", serialize = false, deserialize = false)
    private int age;

    // ordinal指定顺序
    @JSONField(name = "LAST NAME", ordinal = 2)
    private String lastName;

    @JSONField(name = "FIRST NAME", ordinal = 1)
    private String firstName;

    // format格式化
    @JSONField(name = "DATE OF BIRTH", format = "dd/MM/yyyy",ordinal = 3)
    private Date dateOfBirth;

}

以下是我们可以与 @JSONField 注解一起使用的最基本参数列表,以便自定义转换过程:

  • 参数格 format 用于正确格式化日期属性
  • 默认情况下,fastjson 库完全序列化Java bean,但我们可以使用参数 -serialize来忽略特定字段的序列化
  • 参数 ordinal 用于指定字段顺序

这是新的输出:

代码语言:javascript
复制
[
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Jhon",
        "DATE OF BIRTH":"31/01/2019"
    },
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Janette",
        "DATE OF BIRTH":"31/01/2019"
    }
]

fastjson 还支持非常有趣的 BeanToArray 序列化功能:

代码语言:javascript
复制
String jsonOutput= JSON.toJSONString(listOfPersons, SerializerFeature.BeanToArray);

这是在这种情况下输出的样子:

代码语言:javascript
复制
[
    [
        15,
        1469003271063,
        "John Doe"
    ],
    [
        20,
        1469003271063,
        "Janette Doe"
    ]
]

完整示例:

代码语言:javascript
复制
private List<Person> listOfPersons;

    @BeforeTest
    public void setUp() {
        listOfPersons = new ArrayList<Person>();
        // 获取当前时间,取得一个Calendar的实例
        Calendar calendar = Calendar.getInstance();
        // 设置日历
        calendar.set(2019, 01, 31);
        // 实例化Java对象
        listOfPersons.add(new Person(15, "John", "Doe", calendar.getTime()));
        listOfPersons.add(new Person(20, "Janette", "Doe", calendar.getTime()));
    }

    @Test(description = "将Java对象转换为JSON格式")
    public void whenJavaList_thanConvertToJsonCorrect() {

        // 将Java对象转换为JSON字符串
        String personJsonFormat = JSON.toJSONString(listOfPersons);
        // 断言字符串是否相同
        Assert.assertEquals(personJsonFormat, "[{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"John\",\"DATE OF BIRTH\":"
                + "\"01/02/2019\"},{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"Janette\",\"DATE OF BIRTH\":"
                + "\"01/02/2019\"}]");
    }

创建JSON对象

与其他 JSON 库一样,从头开始创建 JSON 对象非常简单,只需要组合JSONObject 和 JSONArray 对象:

代码语言:javascript
复制
@Test(description = "创建JSON对象")
    public void whenGenerateJson_thanGenerationCorrect() {
        // 组合JSONObject和JSONArray对象
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < 2; i++) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("FIRST NAME", "John" + i);
            jsonObject.put("LAST NAME", "Doe" + i);
            jsonObject.put("DATE OF BIRTH", "2019/2/1 12:12:12");
            jsonArray.add(jsonObject);
        }

        Assert.assertEquals(jsonArray.toString(), "[{\"LAST NAME\":\"Doe0\",\"DATE OF BIRTH\":"
                + "\"2019/2/1 12:12:12\",\"FIRST NAME\":\"John0\"},{\"LAST NAME\":\"Doe1\","
                + "\"DATE OF BIRTH\":\"2019/2/1 12:12:12\",\"FIRST NAME\":\"John1\"}]");
        System.out.println(jsonArray.toString());
    }

以下是输出结果:

代码语言:javascript
复制
[
   {
      "LAST NAME":"Doe0",
      "DATE OF BIRTH":"2019/2/1 12:12:12",
      "FIRST NAME":"John0"
   },
   {
      "LAST NAME":"Doe1",
      "DATE OF BIRTH":"2019/2/1 12:12:12",
      "FIRST NAME":"John1"
   }
]

将JSON字符串解析为Java对象

现在我们知道如何从头开始创建 JSON 对象,以及如何将 Java 对象转换为它们的 JSON 格式,让我们把重点放在如何解析 JSON 格式上:

代码语言:javascript
复制
@Test(description = "将JSON字符串解析为Java对象")
    public void whenJson_thanConvertToObjectCorrect() {
        // 将Java对象转换为JSON字符串
        String personJsonFormat = JSON.toJSONString(listOfPersons.get(0));
        System.out.println(personJsonFormat);

        // 从JSON字符串中获取Java对象
        Person newPerson = JSON.parseObject(personJsonFormat, Person.class);
        System.out.println(newPerson.toString());

        // 使用参数serialize忽略Age字段的序列化
        Assert.assertEquals(newPerson.getAge(), 0);
        System.out.println(newPerson.getAge());

        Assert.assertEquals(newPerson.getFirstName(), listOfPersons.get(0).getFirstName());
        System.out.println(newPerson.getFirstName());

        Assert.assertEquals(newPerson.getLastName(), listOfPersons.get(0).getLastName());
        System.out.println(newPerson.getLastName());
    }

我们可以使用 JSON.parseObject() 从 JSON 字符串中获取 Java 对象。 请注意,如果已经声明了自己的参数化构造函数,则必须定义 no-args 或默认构造函数,否则将抛出 com.alibaba.fastjson.JSONException

这是新创建的对象。

代码语言:javascript
复制
Person(age=0, lastName=John, firstName=Doe, dateOfBirth=Sun JAN 31 00:00:00 CST 2019)

使用ContextValueFilter配置JSON转换

在某些情况下,我们可能需要更多地控制从 Java 对象到 JSON 格式的转换过程。 在这种情况下,我们可以使用 ContextValueFilter 对象对转换流应用其他过滤和自定义处理:

代码语言:javascript
复制
@Test(description = "使用ContextValueFilter配置JSON转换")
    public void givenContextFilter_whenJavaObject_thanJsonCorrect() {
        // 使用ContextValueFilter对象对转换流应用其他过滤和自定义处理
        ContextValueFilter valueFilter = new ContextValueFilter() {
            public Object process(BeanContext context, Object object, String name, Object value) {
                // 隐藏了 DATE OF BIRTH 字段,强制一个常量值
                if (name.equals("DATE OF BIRTH")) {
                    return "NOT TO DISCLOSE";
                }
                // 忽略了所有不是John或Doe的字段
                if (value.equals("John") || value.equals("Doe")) {
                    return ((String) value).toUpperCase();
                } else {
                    return null;
                }
            }
        };
        // 将Java对象转换为JSON字符串并过滤及自定义处理
        String personJsonFormat = JSON.toJSONString(listOfPersons, valueFilter);
        System.out.println(personJsonFormat);

    }

在这个例子中,我们隐藏了 DATE OF BIRTH 字段,通过强制一个常量值,我们也忽略了所有不是 John 或 Doe 的字段:

代码语言:javascript
复制
[
   {
      "FIRST NAME":"DOE",
      "LAST NAME":"JOHN",
      "DATE OF BIRTH":"NOT TO DISCLOSE"
   },
   {
      "FIRST NAME":"DOE",
      "DATE OF BIRTH":"NOT TO DISCLOSE"
   }
]

正如你所看到的,这是一个非常基本的示例,当然可以在更复杂的测试场景中使用相同的概念 - 结合 fastjson 在实际项目中提供的这些功能强大且轻量级的工具集。

使用NameFilter和SerializeConfig

fastjson 提供了一组工具来在处理任意对象时自定义 JSON 操作 - 我们没有源码的对象。

让我们假设我们有一个最初在本文中声明的 Person Java bean 的编译版本,我们需要对字段命名和基本格式进行一些增强:

代码语言:javascript
复制
@Test(description = "使用NameFilter和SerializeConfig")
    public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() {

        // formatName过滤器来处理字段名称。
        NameFilter formatName = new NameFilter() {
            public String process(Object object, String name, Object value) {
                return name.toLowerCase().replace(" ", "_");
            }
        };
        SerializeConfig.getGlobalInstance().addFilter(Person.class, formatName);

        // 将对象转换为JSON格式,快速在日期字段上应用相同的格式规则。
        String jsonOutput = JSON.toJSONStringWithDateFormat(listOfPersons, "yyyy-MM-dd");

        System.out.println(jsonOutput);
        Assert.assertEquals(jsonOutput, "[{\"first_name\":\"Doe\",\"last_name\":\"John\","
                + "\"date_of_birth\":\"2019-02-01\"},{\"first_name\":\"Doe\",\"last_name\":"
                + "\"Janette\",\"date_of_birth\":\"2019-02-01\"}]");


        // 重新设置自定义序列化器
        SerializeConfig.getGlobalInstance().put(Person.class, null);
    }

我们使用 NameFilter 匿名类声明了 formatName 过滤器来处理字段名称。新创建的过滤器与 Person 类相关联,然后添加到全局实例 - 它基本上是 SerializeConfig 类中的静态属性。 现在我们可以轻松地将对象转换为 JSON 格式,如本文前面所示。

请注意,我们使用了 toJSONStringWithDateFormat() 而不是 toJSONString() 来快速在日期字段上应用相同的格式规则。

这是输出:

代码语言:javascript
复制
[
   {
      "first_name":"Doe",
      "last_name":"John",
      "date_of_birth":"2019-01-31"
   },
   {
      "first_name":"Doe",
      "last_name":"Janette",
      "date_of_birth":"2019-01-31"
   }
]

如你所见 - 字段名称已更改,日期值确实已正确格式化。

将 SerializeFilter 与 ContextValueFilter 相结合可以完全控制任意和复杂Java 对象的转换过程。

小结

在本文中,我们展示了如何使用 fastjson 将Javabean 转换成 JSON 字符串,以及如何反过来。我们还展示了如何使用 fastjson 的一些核心特性来定制 JSON 输出。 fastjson库提供了一个相对简单但仍然非常强大的API,JSON.toJSONStringJSON.parseObject 可满足大多数需求。

本文源码:

https://github.com/7DGroup/Java-API-Test-Examples/tree/master/SpringBoot-fastjson-demo

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 7DGroup 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是fastjson?
  • fastjson的特点
    • 速度快
      • 使用广泛
        • 测试完备
          • 使用简单
            • 功能完备
            • fastjson使用
              • Maven配置
                • 将Java对象转换为JSON格式
                  • 创建JSON对象
                    • 将JSON字符串解析为Java对象
                      • 使用ContextValueFilter配置JSON转换
                        • 使用NameFilter和SerializeConfig
                        • 小结
                        相关产品与服务
                        文件存储
                        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档