fastjson和jackson使用对比

介绍

Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。无依赖,不需要例外额外的jar,能够直接跑在JDK上。 FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。 FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
Jackson是当前用的比较广泛的,用来序列化和反序列化json的Java开源框架。Jackson社区相对比较活跃,更新速度也比较快, 从Github中的统计来看,Jackson是最流行的json解析器之一,Spring MVC的默认json解析器便是Jackson。

添加maven依赖

<!--fastjson依赖-->
<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.56</version>
 </dependency>
<!--jackson依赖-->
 <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.4</version>
</dependency>
<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.4</version>
</dependency>

将java bean序列化为json字符串

过滤null值

public class Client1 {

  public static void main(String[] args) {
    User user = new User();
    user.setUsername("lisi");
    System.out.println(JSON.toJSONString(user));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}

fastjson将javabean转成字符串,结果为:{"username":"lisi"},默认过滤null值

public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("lisi");
    ObjectMapper objectMapper = new ObjectMapper();
    //只包含非null值
    objectMapper.setSerializationInclusion(Include.NON_NULL);
    System.out.println(objectMapper.writeValueAsString(user));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}

jackson默认保留null值

保留null值

如果不想过滤,fastjson可以使用以下方式

public class Client1 {

  public static void main(String[] args) {
    User user = new User();
    user.setUsername("lisi");
    //保留null值
    System.out.println(JSON.toJSONString(user, SerializerFeature.WriteMapNullValue));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}

结果为:{"password":null,"username":"lisi"}

public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("lisi");
    ObjectMapper objectMapper = new ObjectMapper();
    System.out.println(objectMapper.writeValueAsString(user));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}

jackson默认就是保留null值

美化显示

public class Client1 {

  public static void main(String[] args) {
    User user = new User();
    user.setUsername("lisi");
    //保留null值,字符串格式化方式显示
    System.out.println(JSON.toJSONString(user, SerializerFeature.WriteMapNullValue,
        SerializerFeature.PrettyFormat));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}
public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("lisi");
    ObjectMapper objectMapper = new ObjectMapper();
    System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
  }

  @Setter
  @Getter
  static class User {

    private String username;
    private String password;
  }
}

输出为:

{
	"password":null,
	"username":"lisi"
}

忽略属性和属性别名

public class Client1 {

  public static void main(String[] args) {
    User user = new User();
    user.setOpenId("lisi");
    user.setPassword("123456");
    System.out.println(JSON.toJSONString(user));
  }

  @Setter
  @Getter
  @ToString
  static class User {

    /**
     * 序列化忽略
     */
    @JSONField(serialize = false)
    private String openId;
    /**
     * 序列化名称为pwd
     */
    @JSONField(name = "pwd")
    private String password;
  }
}

fastjson的JSONField注解提供了多种功能的组合

public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("lisi");
    user.setPassword("123456");
    ObjectMapper objectMapper = new ObjectMapper();
    System.out.println(objectMapper.writeValueAsString(user));
  }

  @Setter
  @Getter
  static class User {

    @JsonIgnore
    private String username;
    @JsonProperty("pwd")
    private String password;
  }
}

jackson不同的功能使用不同的注解来实现

json字符串反序列化为java bean

未知属性报错

public class Client1 {

  public static void main(String[] args) {
    String jsonStr = "{\"username\":\"lisi\",\"pwd\":\"123456\"}";
    int featureValue = JSON.DEFAULT_PARSER_FEATURE & ~Feature.IgnoreNotMatch.getMask();
    User user = JSON.parseObject(jsonStr, User.class, featureValue);
    System.out.println(user);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

fastjson默认会忽略未知属性

所以我们要将忽略未知属性的特性去掉

public class Client2 {

  public static void main(String[] args) throws IOException {
    String jsonStr = "{\"username\":\"lisi\",\"pwd\":\"123456\"}";
    ObjectMapper objectMapper = new ObjectMapper();
    User user = objectMapper.readValue(jsonStr, User.class);
    System.out.println(user);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

jackson默认未知属性报错

忽略未知属性

public class Client1 {

  public static void main(String[] args) {
    String jsonStr = "{\"username\":\"lisi\",\"pwd\":\"123456\"}";
    User user = JSON.parseObject(jsonStr, User.class);
    System.out.println(user);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

fastjson默认忽略未知属性

public class Client2 {

  public static void main(String[] args) throws IOException {
    String jsonStr = "{\"username\":\"lisi\",\"pwd\":\"123456\"}";
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    User user = objectMapper.readValue(jsonStr, User.class);
    System.out.println(user);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

jackson默认未知属性报错,但也提供了反序列化特性来支持忽略。我们在项目中一般也是要配置为忽略未知属性的,防止调用方接口升级影响到我们。

将java bean 数组序列化为字符串

public class Client1 {

  public static void main(String[] args) {
    List<User> userList = Arrays.asList(new User("lisi", "123"), new User("Tony", "456"));
    System.out.println(JSON.toJSONString(userList));
  }

  @AllArgsConstructor
  @NoArgsConstructor
  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}
public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    List<User> userList = Arrays.asList(new User("lisi", "123"), new User("Tony", "456"));
    ObjectMapper objectMapper = new ObjectMapper();
    System.out.println(objectMapper.writeValueAsString(userList));
  }

  @AllArgsConstructor
  @NoArgsConstructor
  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

json字符串反序列化为java bean数组

public class Client1 {

  public static void main(String[] args) {
    String jsonStr = "[{\"username\":\"lisi\",\"password\":\"123\"},{\"username\":\"Tony\",\"password1\":\"456\"}]";
    List<User> userList = JSON.parseArray(jsonStr, User.class);
    System.out.println(userList);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

fastjson反序列化数组和反序列化bean一样简单

public class Client2 {

  public static void main(String[] args) throws IOException {
    String jsonStr = "[{\"username\":\"lisi\",\"password\":\"123\"},{\"username\":\"Tony\",\"password\":\"456\"}]";
    ObjectMapper objectMapper = new ObjectMapper();
    List<User> userList = objectMapper.readValue(jsonStr, new TypeReference<List<User>>() {
    });
    System.out.println(userList);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}
public class Client2 {

  public static void main(String[] args) throws IOException {
    String jsonStr = "[{\"username\":\"lisi\",\"password\":\"123\"},{\"username\":\"Tony\",\"password\":\"456\"}]";
    ObjectMapper objectMapper = new ObjectMapper();
    //创建一个泛型类型
    JavaType javaType = objectMapper.getTypeFactory()
        .constructParametricType(List.class, User.class);
    List<User> userList = objectMapper.readValue(jsonStr, javaType);
    System.out.println(userList);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    private String password;
  }
}

上述两种方式都可以反序列化泛型集合或集合

属性拦截器

public class Client1 {

  public static void main(String[] args) {
    User user = new User();
    user.setUsername("lisi");
    user.setPassword("123");
    user.setGender("male");
    user.setAge(28);
    PropertyFilter securedFieldFilter = (object, name, value) -> {
      Class<?> clazz = object.getClass();
      List<Field> fieldList = Arrays.asList(clazz.getDeclaredFields());
      Map<String, Field> fieldMap = fieldList.stream()
          .collect(Collectors.toMap(Field::getName, Function.identity()));
      Field field = fieldMap.get(name);
      return !Objects.nonNull(field) || !field.isAnnotationPresent(SecuredField.class);
    };
    String jsonStr = JSON.toJSONString(user, securedFieldFilter);
    System.out.println(jsonStr);
  }

  @Setter
  @Getter
  @ToString
  static class User {

    private String username;
    @SecuredField
    private String password;
    private String gender;
    private Integer age;
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  static @interface SecuredField {

  }

}

定义一个SecuredField 注解,包含此注解的属性就过滤,fastjson提供了PropertyFilter 来支持该功能。

public class Client2 {

  public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("lisi");
    user.setPassword("123");
    user.setGender("male");
    user.setAge(28);
    ObjectMapper objectMapper = new ObjectMapper();
    PropertyFilter propertyFilter = new SimpleBeanPropertyFilter() {
      @Override
      public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider,
          PropertyWriter writer) throws Exception {
        if (Objects.isNull(writer.getAnnotation(SecuredField.class))) {
          writer.serializeAsField(pojo, jgen, provider);
        }
      }
    };
    //id要和JsonFilter注解的value相同
    FilterProvider filterProvider = new SimpleFilterProvider()
        .addFilter("securedFieldFilter", propertyFilter);
    System.out.println(objectMapper.setFilterProvider(filterProvider).writeValueAsString(user));
  }


  @Setter
  @Getter
  @ToString
  @JsonFilter("securedFieldFilter")
  static class User {

    private String username;
    @SecuredField
    private String password;
    private String gender;
    private Integer age;
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  static @interface SecuredField {

  }

}

jackson通过JsonFilter注解和PropertyFilter 接口提供属性过滤的功能。

posted @ 2020-10-31 17:19  strongmore  阅读(5091)  评论(0编辑  收藏  举报