走进Java接口测试之fastjson指南

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

欢迎大家来到IT世界,在知识的湖畔探索吧!

走进Java接口测试之fastjson指南

一、引言

在上文 走进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的特点

1、速度快

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

2、使用广泛

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

3、测试完备

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

4、使用简单

fastjson 的 API 十分简洁。

String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化

欢迎大家来到IT世界,在知识的湖畔探索吧!

5、功能完备

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

四、fastjson使用

1、Maven配置

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

欢迎大家来到IT世界,在知识的湖畔探索吧!  <!--引入效率插件-->
        <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>

2、将Java对象转换为JSON格式

让我们定义以下Person Java bean

@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 字符串

欢迎大家来到IT世界,在知识的湖畔探索吧!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);
}

这是结果:

[  
    {  
        "AGE":15,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"John Doe"
    },
    {  
        "AGE":20,
        "DATE OF BIRTH":1468962431394,
        "FULL NAME":"Janette Doe"
    }
]

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

@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 用于指定字段顺序

这是新的输出:

[
    {
        "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 序列化功能:

String jsonOutput= JSON.toJSONString(listOfPersons, SerializerFeature.BeanToArray);

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

[
    [
        15,
        1469003271063,
        "John Doe"
    ],
    [
        20,
        1469003271063,
        "Janette Doe"
    ]
]

完整示例:

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\"}]");
 }

3、创建JSON对象

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

@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());
 }

以下是输出结果:

[
   {
      "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"
   }
]

4、将JSON字符串解析为Java对象

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

@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

这是新创建的对象。

Person(age=0, lastName=John, firstName=Doe, dateOfBirth=Sun JAN 31 00:00:00 CST 2019)

5、使用ContextValueFilter配置JSON转换

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

@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 的字段:

[
   {
      "FIRST NAME":"DOE",
      "LAST NAME":"JOHN",
      "DATE OF BIRTH":"NOT TO DISCLOSE"
   },
   {
      "FIRST NAME":"DOE",
      "DATE OF BIRTH":"NOT TO DISCLOSE"
   }
]

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

6、使用NameFilter和SerializeConfig

fastjson 提供了一组工具来在处理任意对象时自定义 JSON 操作 – 我们没有源码的对象。 让我们假设我们有一个最初在本文中声明的 Person Java bean 的编译版本,我们需要对字段命名和基本格式进行一些增强:

 @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() 来快速在日期字段上应用相同的格式规则。

这是输出:

[
   {
      "first_name":"Doe",
      "last_name":"John",
      "date_of_birth":"2019-03-03"
   },
   {
      "first_name":"Doe",
      "last_name":"Janette",
      "date_of_birth":"2019-03-03"
   }
]

如你所见 – 字段名称已更改,日期值确实已正确格式化。 将 SerializeFilter 与 ContextValueFilter 相结合可以完全控制任意和复杂Java 对象的转换过程。

五、小结

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

本文源码:

  • https://github.com/zuozewei/blog-example/tree/master/Java-api-test/00-testdata/springboot-fastjson-demo

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/36636.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信