Contents

Fastjson 简介

1. 概述

FastJson 是一个轻量级的 Java 库,用于有效地将 JSON 字符串转换为 Java 对象,反之亦然。

在本文中,我们将深入探讨 FastJson 库的几个具体和实际应用。

2. Maven配置

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

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.13</version>
</dependency>

作为一个简短的说明 -这是 Maven Central 上库的最新版本

3. 将 Java 对象转换为 JSON 格式

让我们定义以下Person Java bean:

public class Person {
    
    @JSONField(name = "AGE")
    private int age;
    @JSONField(name = "FULL NAME")
    private String fullName;
    @JSONField(name = "DATE OF BIRTH")
    private Date dateOfBirth;
    public Person(int age, String fullName, Date dateOfBirth) {
        super();
        this.age = age;
        this.fullName= fullName;
        this.dateOfBirth = dateOfBirth;
    }
    // standard getters & setters
}

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

private List<Person> listOfPersons = new ArrayList<Person>();
@Before
public void setUp() {
    listOfPersons.add(new Person(15, "John Doe", new Date()));
    listOfPersons.add(new Person(20, "Janette Doe", new Date()));
}
@Test
public void whenJavaList_thanConvertToJsonCorrect() {
    String jsonOutput= JSON.toJSONString(listOfPersons);
}

结果如下:

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

我们还可以更进一步,开始自定义输出并控制诸如排序、日期格式序列化标志之类的东西。

例如——让我们更新 bean 并添加更多字段:

@JSONField(name="AGE", serialize=false)
private int age;
@JSONField(name="LAST NAME", ordinal = 2)
private String lastName;
@JSONField(name="FIRST NAME", ordinal = 1)
private String firstName;
@JSONField(name="DATE OF BIRTH", format="dd/MM/yyyy", ordinal = 3)
private Date dateOfBirth;

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

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

这是新的输出:

[
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Jhon",
        "DATE OF BIRTH":"19/07/2016"
    },
    {
        "FIRST NAME":"Doe",
        "LAST NAME":"Janette",
        "DATE OF BIRTH":"19/07/2016"
    }
]

FastJson 还支持一个非常有趣的BeanToArray序列化特性:

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

在这种情况下,输出如下所示:

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

4. 创建 JSON 对象

其他 JSON 库 一样,从头开始创建 JSON 对象非常简单,只需组合JSONObjectJSONArray 对象即可:

@Test
public void whenGenerateJson_thanGenerationCorrect() throws ParseException {
    JSONArray jsonArray = new JSONArray();
    for (int i = 0; i < 2; i++) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("AGE", 10);
        jsonObject.put("FULL NAME", "Doe " + i);
        jsonObject.put("DATE OF BIRTH", "2016/12/12 12:12:12");
        jsonArray.add(jsonObject);
    }
    String jsonOutput = jsonArray.toJSONString();
}

这里的输出如下所示:

[
   {
      "AGE":"10",
      "DATE OF BIRTH":"2016/12/12 12:12:12",
      "FULL NAME":"Doe 0"
   },
   {
      "AGE":"10",
      "DATE OF BIRTH":"2016/12/12 12:12:12",
      "FULL NAME":"Doe 1"
   }
]

5. 将 JSON 字符串解析为 Java 对象

既然我们知道了如何从头开始创建 JSON 对象,以及如何将 Java 对象转换为它们的 JSON 表示形式,那么让我们将重点放在如何解析 JSON 表示形式上:

@Test
public void whenJson_thanConvertToObjectCorrect() {
    Person person = new Person(20, "John", "Doe", new Date());
    String jsonObject = JSON.toJSONString(person);
    Person newPerson = JSON.parseObject(jsonObject, Person.class);
    
    assertEquals(newPerson.getAge(), 0); // if we set serialize to false
    assertEquals(newPerson.getFullName(), listOfPersons.get(0).getFullName());
}

我们可以使用***JSON.parseObject()***从 JSON 字符串中获取 Java 对象。

请注意,如果您已经声明了自己的参数化构造函数,则必须定义无参数或默认构造函数,否则将抛出com.alibaba.fastjson.JSONException

这是这个简单测试的输出:

Person [age=20, fullName=John Doe, dateOfBirth=Wed Jul 20 08:51:12 WEST 2016]

通过在*@JSONField*注解中使用选项反序列化,我们可以忽略特定字段的反序列化,在这种情况下,默认值将自动应用于被忽略的字段:

@JSONField(name = "DATE OF BIRTH", deserialize=false)
private Date dateOfBirth;

这是新创建的对象:

Person [age=20, fullName=John Doe, dateOfBirth=null]

6. 使用ContextValueFilter配置 JSON 转换

在某些情况下,我们可能需要对从 Java 对象到 JSON 格式的转换过程进行更多控制。

在这种情况下,我们可以利用ContextValueFilter对象对转换流应用额外的过滤和自定义处理:

@Test
public void givenContextFilter_whenJavaObject_thanJsonCorrect() {
    ContextValueFilter valueFilter = new ContextValueFilter () {
        public Object process(
          BeanContext context, Object object, String name, Object value) {
            if (name.equals("DATE OF BIRTH")) {
                return "NOT TO DISCLOSE";
            }
            if (value.equals("John")) {
                return ((String) value).toUpperCase();
            } else {
                return null;
            }
        }
    };
    String jsonOutput = JSON.toJSONString(listOfPersons, valueFilter);
}

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

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

如您所见,这是一个非常基本的示例,但您当然也可以将相同的概念用于更复杂的场景——将 FastJson 提供的这些强大且轻量级的工具集结合到一个真实世界的项目中。

7. 使用NameFilterSerializeConfig

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

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

@Test
public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() {
    NameFilter formatName = new NameFilter() {
        public String process(Object object, String name, Object value) {
            return name.toLowerCase().replace(" ", "_");
        }
    };
    
    SerializeConfig.getGlobalInstance().addFilter(Person.class,  formatName);
    String jsonOutput = 
      JSON.toJSONStringWithDateFormat(listOfPersons, "yyyy-MM-dd");
}

我们已经使用NameFilter匿名类声明了formatName过滤器来处理字段名称。新创建的过滤器与Person类相关联,然后添加到全局实例中——这基本上是SerializeConfig类中的静态属性。

现在我们可以轻松地将我们的对象转换为 JSON 格式,如本文前面所示。

请注意,我们使用***toJSONStringWithDateFormat()**而不是toJSONString()*来快速将相同的格式规则应用于日期字段。 这是输出:

[  
    {  
        "full_name":"John Doe",
        "date_of_birth":"2016-07-21"
    },
    {  
        "full_name":"Janette Doe",
        "date_of_birth":"2016-07-21"
    }
]

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

SerializeFilterContextValueFilter 结合使用可以完全控制任意和复杂 Java 对象的转换过程。