阿里巴巴FastJson整理(20分钟阅读)

简介: 阿里巴巴FastJson整理(20分钟阅读)

一、简介

1、Json简介

1.1.1 什么是json

JSON:(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。目前,Json处于数据交换语言的王者地位.

1.1.2 Json数组格式

Json的数据本身是数组,中括号包裹,数组的元素之间逗号分开.数组元素的数据类型没有限制.

var jsonArray = ["元素1","元素2","元素3"]; //定义数组格式json
console.log(jsonArray[0]); //访问json数组的元素
for(var i = 0 ; i < jsonArray.length ; i++){
    console.log(jsonArray[i]); //遍历数组,访问每个元素
}
1.1.3 Json对象格式

Json的数据本身是对象,大括号包裹.对象采用键值对形式存储,键固定为字符串类型,值是任意类型的数据.键和值使用冒号分开.

var jsonObject = {"k1":"v1","k2":"v2","k3":"v3"}; //定义对象格式json
console.log(jsonObject.k1); //取出键k1对应的值
1.1.4 数组对象相互嵌套格式
  1. 数组中的元素是对象
var jsonArray = [
    {"k1":"v1"},{"k2":"v2"}
]; // 定义数组格式json,数组元素是对象
console.log(jsonArray[0].k1); //访问数组0索引的元素,该元素的键k1对应的值
  1. 对象中的值是数组
var jsonObject = {
    "k1":["元素1","元素2"],
    "k2":["元素1","元素2"]
}; // 定义对象格式json,键是字符串类型,值是数组
console.log(jsonObject.k1[0]); //访问对象的键是k1,对于的值为数组,数组的0索引元素
  1. 你中有我,我中有你
var json = {
    "k1":[
      "元素1",{"key1":"value1"},{"key2":"value2"}  
    ],
    "k2":[
        {"key1":"value1"}
    ]
}; //定义对象格式json,键是字符串,值是数组,数组的元素是对象
console.log(json.k1[1].key1); //访问json对象的键k1,对应的是数组,访问数组的1索引,数组的1索引上的元素是对象,访问key1键对应的值

2、FastJson简介

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

Fastjson 的优点

  • 速度快
    fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
  • 使用广泛
    fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
  • 测试完备
    fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
  • 使用简单
    fastjson的 API 十分简洁。
  • 功能完备
    支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。

二、序列化API

序列化 : 是指将Java对象转成json格式字符串的过程.JavaBean对象,List集合对象,Map集合,为应用最广泛的.Sy

JSON.toJSONString(students):可以支持对象,集合,map多种数据类型。

String jsonString = JSON.toJSONString(student);

序列化Java对象

Student student = new Student();
student.setName("张三");
student.setAge(20);
String jsonString = JSON.toJSONString(student);

序列化集合(List)

Student student = new Student();
student.setEmail("zs@sina.com");
Student student1 = new Student();
student1.setId(1);
ArrayList<Student> students = new ArrayList<>(
students.add(student);
students.add(student1);
  //  序列化
String s = JSON.toJSONString(students);

序列化Map

HashMap<String, String> map = new HashMap<>();
 map.put("name","张三");
 String s1 = JSON.toJSONString(map);

三、反序列化API

1、解析Java对象

//  JSON类的静态方法 parseObject
//  传递要反序列化的Json字符串,传递Java对象的Class对象
String objectString="{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"}";
Student student = JSON.parseObject(objectString, Student.class);

2、解析List集合

//  JSON类的静态方法,parseArray
//  传递Json格式字符串,传递转换后的集合的泛型的Class对象
String listString="[{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"},{\"address\":\"北京市\",\"age\":20,\"id\":1,\"name\":\"张三\"}]";
List<Student> students = JSON.parseArray(listString, Student.class);

3、解析Map集合

//  JSON类的静态方法 parseObject
//  传递要反序列化的Json字符串、要序列化的类型接口
String jsonString="{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"}";
Map<String, String> map = JSON.parseObject(jsonString, new TypeReference<Map<String, String>>() {});

4、JSONObject()

JSONObject jsonObject = new JSONObject();
JSONObject user = jsonObject.getJSONObject("user");
JSONArray data = jsonObject.getJSONArray("data");
Student student = jsonObject.toJavaObject(Student.class);

5、JSONArray()

JSONArray jsonArray = new JSONArray();
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
JSONArray jsonArray1 = jsonArray.getJSONArray(0);
List<Student> students = jsonArray.toJavaList(Student.class);

四、固定枚举注解

1、SerializerFeature枚举

该枚举支持序列化的一些特性数据定义。

名称 描述
QuoteFieldNames 输出key时是否使用双引号,默认为true
UseSingleQuotes 使用单引号而不是双引号,默认为false
WriteMapNullValue 是否输出值为null的字段,默认为false
WriteEnumUsingToString Enum输出name()或者original,默认为false
WriteEnumUsingName 用枚举name()输出
UseISO8601DateFormat Date使用ISO8601格式输出,默认为false
WriteNullListAsEmpty List字段如果为null,输出为[],而非null
WriteNullStringAsEmpty 字符类型字段如果为null,输出为”“,而非null
WriteNullNumberAsZero 数值字段如果为null,输出为0,而非null
WriteNullBooleanAsFalse Boolean字段如果为null,输出为false,而非null
SkipTransientField 如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true
SortField 按字段名称排序后输出。默认为false
(过期)WriteTabAsSpecial 把\t做转义输出,默认为false
PrettyFormat 结果是否格式化,默认为false
WriteClassName 序列化时写入类型信息,默认为false。反序列化时需用到
DisableCircularReferenceDetect 消除对同一对象循环引用的问题,默认为false
WriteSlashAsSpecial 对斜杠’/’进行转义
BrowserCompatible 将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE 6,默认为false
WriteDateUseDateFormat 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
(过期)DisableCheckSpecialChar 一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
4.1.1 WriteMapNullValue
//  {"age":10,"id":0,"name":"张三"}
String s = JSON.toJSONString(stu);
//  {"address":null,"age":10,"email":null,"id":null,"name":"张三"}
String s = JSON.toJSONString(stu, SerializerFeature.WriteMapNullValue);
4.1.2 WriteNullNumberAsZero
//  {"age":10,"id":0,"name":"张三"}
String s = JSON.toJSONString(stu);
//  {"age":10,"id":0,"name":"张三"}
String s = JSON.toJSONString(stu, SerializerFeature.WriteNullNumberAsZero);
4.1.3 WriteNullStringAsEmpty
//  {"age":10,"id":0,"name":"张三"}
String s = JSON.toJSONString(stu);
//  {"address":"","age":10,"email":"","name":"张三"}
String s = JSON.toJSONString(stu, SerializerFeature.WriteNullStringAsEmpty);
4.1.4 WriteNullBooleanAsFalse
//  {"age":10,"id":0,"name":"张三"}
String s = JSON.toJSONString(stu);
//  {"age":10,"isBoolean":false,"name":"张三"}
String s = JSON.toJSONString(stu, SerializerFeature.WriteNullBooleanAsFalse);
4.1.5 WriteDateUseDateFormat
{"age":10,"date":1652783554404,"name":"张三"}
String s = JSON.toJSONString(stu);
  {"age":10,"date":"2022-05-17 18:31:59","name":"张三"}
String s = JSON.toJSONString(stu, SerializerFeature.WriteDateUseDateFormat);
4.1.6 PrettyFormat
JSON.toJSONString(stu, SerializerFeature.WriteDateUseDateFormat,SerializerFeature.PrettyFormat);
{
  "age":10,
  "date":"2022-05-17 18:37:11",
  "name":"张三"
}

2、@JSonField注解

该注解作用于方法上,字段上和参数上.可在序列化和反序列化时进行特性功能定制.

  • 注解属性 : name 序列化后的名字
  • 注解属性 : ordinal序列化后的顺序
  • 注解属性 : format 序列化后的格式
  • 注解属性 : serialize 是否序列化该字段
  • 注解属性 : deserialize 是否反序列化该字段
  • 注解属性 : serialzeFeatures 序列化时的特性定义(等同于SerializerFeature枚举)
  • 注解属性:label给属性打上标签, 相当于给属性进行了分组
  • 注解属性:serializeUsing设置属性的序列化类
  • 注解属性:deserializeUsing设置属性的反序列化类
@Data
public class Student {
    //  name 序列化后的名字
    @JSONField(name = "myName")
    private String name;
    //  ordinal序列化后的顺序
    @JSONField(ordinal = 2)
    private Integer age;
    //  ordinal序列化后的顺序
    @JSONField(ordinal = 1)
    private String address;
    //  serialize 是否序列化该字段
    @JSONField(serialize = false)
    private String email;
    //  deserialize 是否反序列化该字段
    @JSONField(deserialize = false)
    private Boolean isBoolean;
    //  序列化时的特性定义
    @JSONField(serialzeFeatures = {SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.PrettyFormat})
    private String desc;
    //  format 序列化后的格式
    @JSONField(format = "YYYY-MM-dd")
    private Date date;
}

3、@JSonType注解

@JSonType@JSONField产生冲突时,@JSONField优先级高。

该注解作用于类上,对该类的字段进行序列化和反序列化时的特性功能定制。

  • 注解属性 : includes 要被序列化的字段。
  • 注解属性 : orders 序列化后的顺序。
  • 注解属性 : serialzeFeatures 序列化时的特性定义(等同于SerializerFeature枚举)。
@Data
@JSONType(
  //  includes 要被序列化的字段
        includes = {"name", "age", "address"},
  //  orders 序列化后的顺序.
        orders = {"age", "name", "address"},
  //  serialzeFeatures 序列化时的特性定义
        serialzeFeatures = {SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.PrettyFormat})
public class Student {
    private String name;
    private Integer age;
//  ordinal序列化后的顺序
    @JSONField(ordinal = 1)
    private String address;
}

五、Springboot集成FastJson做入参解析

  • 配置的是SpringMVC的入参的格式。
  • 假如没有注解配置,则走全局的配置。
  • 假如有注解配置,以字段上的注解配置为准。

1、pom依赖

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

2、配置类

5.2.1 配置代码
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.nio.charset.StandardCharsets;
/**
 * 配置FastJson解析器,默认是Jackson
 */
@Configuration
public class HttpMessageConfig {
    @Bean
    public HttpMessageConverters fasJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
//        FastJsonConfig fastJsonConfig = getJsonCofig();
//        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
//        fastJsonHttpMessageConverter通过封装FastjsonConfig配置全局
        return new HttpMessageConverters(fastJsonHttpMessageConverter);
    }
    private FastJsonConfig getJsonCofig() {
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
//        fastJsonConfig.setSerializerFeatures(); //序列化特性
//        fastJsonConfig.setSerializeConfig();  //序列化配置-个性化
//        fastJsonConfig.setParserConfig(); //反序列化配置
//        fastJsonConfig.setSerializeFilters(); //序列化过滤器
        return fastJsonConfig;
    }
}
5.2.2 FastJsonConfig
public void setCharset(Charset charset);
public void setSerializerFeatures(SerializerFeature... serializerFeatures); 序列化特性
public void setSerializeConfig(SerializeConfig serializeConfig); 序列化配置-个性化
public void setParserConfig(ParserConfig parserConfig); 反序列化配置
public void setSerializeFilters(SerializeFilter... serializeFilters); 序列化过滤器
5.2.3 SerializeConfig
// API
public boolean put(Type type, ObjectSerializer value)
serializeConfig.propertyNamingStrategy = 
    PropertyNamingStrategy.CamelCase/PascalCase/...;

CamelCase策略,Java对象属性:personId,序列化后属性:persionId

PascalCase策略,Java对象属性:personId,序列化后属性:PersonId

SnakeCase策略,Java对象属性:personId,序列化后属性:person_id

KebabCase策略,Java对象属性:personId,序列化后属性:person-id

六、问题解决

1、$ref":"$[0]重复引用

语法 描述
{“r e f " : " ref":"ref":"”} 引用根对象
{“$ref”:“@”} 引用自己
{“$ref”:“…”} 引用父对象
{“$ref”:“…/…”} 引用父对象的父对象
{“r e f " : " ref":"ref":".members[0].reportTo”} 基于路径的引用

解决问题:

全局解决(配置类中):

fastJsonConfig.setSerializerFeatures(
    //去除重复引用
  SerializerFeature.DisableCircularReferenceDetect
)

如果能直接控制到序列化方法的话,可以

JSON.toJSONString(user,SerializerFeature.DisableCircularReferenceDetect);

测试:

SerializerFeature.DisableCircularReferenceDetect:去除重复引用

Student student = new Student();
student.setId(1);
student.setName("张三");
student.setAge(20);
ArrayList<Student> students = new ArrayList<>();
students.add(student);
students.add(student);
System.out.println(JSON.toJSONString(students));
System.out.println(JSON.toJSONString(students, SerializerFeature.DisableCircularReferenceDetect));

结果:

[{"desc":"","id":1,"myName":"张三","age":20},{"$ref":"$[0]"}]
===========
[{"desc":"","id":1,"myName":"张三","age":20},{"desc":"","id":1,"myName":"张三","age":20}]

2、BigDecimal类型设置

方案一:使用SerializeFilter处理

FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
SerializeConfig serializeConfig = new SerializeConfig();
fastJsonConfig.setSerializeConfig(serializeConfig);
PropertyFilter propertyFilter = new PropertyFilter() {
    @Override
    public boolean apply(Object object, String name, Object value) {
        if(value instanceof BigDecimal){
            return false;
        }
        return true;
    }
};
AfterFilter afterFilter = new AfterFilter() {
    @Override
    public void writeAfter(Object object) {
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.getType() == BigDecimal.class) {
                field.setAccessible(true);
                Object value= null;
                try {
                    value = (BigDecimal)field.get(object);
                    value = ((BigDecimal) value).setScale(2,BigDecimal.ROUND_DOWN);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                writeKeyValue(field.getName(), value );
            }
        }
    }
};
fastJsonConfig.setSerializeFilters(propertyFilter,afterFilter);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);

方案二:

ValueFilter valueFilter = new ValueFilter() {
    @Override
    public Object process(Object object, String name, Object value) {
        if(value instanceof BigDecimal){
            value = ((BigDecimal)value).setScale(3,BigDecimal.ROUND_DOWN);
        }
        return value;
    }
};
fastJsonConfig.setSerializeFilters(valueFilter);
目录
相关文章
|
3天前
|
安全 架构师 Java
理论实战源码齐飞!架构师社区疯传的SpringSecurity进阶小册真香
安全管理是Java应用开发中无法避免的问题,随着Spring Boot和微服务的流行,Spring Security受到越来越多Java开发者的重视,究其原因,还是沾了微服务的光。作为Spring家族中的一员,其在和Spring家族中的其他产品如SpringBoot、Spring Cloud等进行整合时,是拥有众多同类型框架无可比拟的优势的。
56 0
|
7月前
|
设计模式 算法 NoSQL
冲刺金九银十!GitHub 中文社区高热度的 Java 面试题被我整理好了!
面对已经过去的金三银四很多小伙伴都受到了很大的挫折! 最近收到一个小伙伴金三银四在阿里的面试流程完全被吊打,和我一起看看阿里都问了什么吧! 小编在这里也简单的看了一下牛客网阿里招聘的一些评价,难度指数普遍在四星以上!!!! 太难了! 因此收到了一个面试失败的粉丝回复,面试失败了 前几天小编整理了一些热度高的面试题现在分享给大家! 转发+关注后私信(学习)免费获取! GitHub最热Java面试总结 这份总结涵盖技术点有:Java基础,JVM,多线程高并发,redis,微服务,分布式,算法,操作系统,spring全家桶,MySQL,设计模式,计算机网络,Li
冲刺金九银十!GitHub 中文社区高热度的 Java 面试题被我整理好了!
|
6月前
|
设计模式 Java 数据库
持续霸榜GitHub的面试神器:字节跳动Java面试参考手册,限时开源
最近又赶上跳槽的高峰期(招聘旺季),好多读者都问我有没有面试字节的神器,我苦苦寻到了一份内部资料《2023字节跳动Java面试参考手册(第二期)》。
|
3天前
|
存储 算法 Java
超全面!阿里巴巴最新发布23年秋招200道Java面试题(含答案)
马上过34岁生日了,和大家聊聊最近的情况 半年前还在迷茫该学什么,怎样才能走出现在的困境,半年后已经成功上岸阿里,感谢在这期间帮助我的每一个人。 面试中总结了200道经典的Java面试题,里面包含面试要回答的知识重点,并且我根据知识类型进行了分类,可以说非常全面了~ 因为篇幅原因,大部分的内容就不给大家一一展示了,需要获取的小伙伴可以直接点击此处取到! Java平台相关 1、JDK、JRE、JVM 分别是什么关系? 2、为什么 Java 被称作是“平台无关的编程语言”? 3、Java 和 C++ 的区别? 4、什么是字节码?采用字节码的最大好处是什么? 5、Java运行的过程? 6、
100 4
|
10月前
|
Java 程序员
GitHub最新发布Java面试突击手册+P5-P8学习图谱,一夜直接竟爆火
什么是金九银十? “金九银十指的是每年的九十月份都是人才招聘的高峰期,因为跟春节和春运紧接,到人才市场,人都是满的,所以称为金九;伴随的十月则称为银十。”
|
3天前
|
监控 安全 Java
腾讯T4大牛整理的SpringBoot文档,覆盖你认知中的所有操作
SpringBoot目前的使用已经很普遍了,实际的项目中,我们需要集成各种的插件支持,不仅如此,还有很多可能我们平时不知道,但是很方便的操作。pdf里面的东西还是比较全面的。
|
3天前
|
Java 关系型数据库 MySQL
太牛了! GitHub大牛呕心沥血整理的5000页Java学习手册文档
今天整理了一套 5000 页的 Java 学习手册,,新鲜出炉,分享给大家!此手册内容专注 Java技术,包括 JavaWeb,SSM,Linux,Spring Boot,MyBatis,MySQL,Nginx,Git,GitHub,Servlet,IDEA,多线程,集合,JVM,DeBug, Dubbo,Redis,算法,面试题等相关内容。
|
7月前
|
缓存 算法 搜索推荐
阿里资深架构师三年整理分享:java面试核心知识点原理篇文档
前言 本文是对Java程序员面试必备知识点的总结,详细讲解了JVM原理、多线程、数据结构和算法、分布式缓存、设计模式等内容,希望读者能通过阅读本书对Java的基础原理有更深入、全面的理解。 面试官通常会在短短两小时内对面试者的知识结构进行全面了解,面试者在回答问题时如果拖泥带水且不能直击问题的本质,则很难充分表现自己,最终影响面试结果。针对这种情况,本文在讲解知识点时不拖泥带水,力求精简,详细介绍了Java程序员面试时常被问及的核心知识点。
95 0
|
7月前
|
架构师 Java
阿里P8面试7分看能力,3分靠嘴皮,这份绝版Java面试神册.PDF
古人有句话语,说得好面试中7分靠能力,3分靠嘴皮 前几天面了一位91年的java架构师,他工作 8 年,5年java后端开发经验,从事架构设计只有短短 3 年时间,上份工作已经10万月薪了。但让我惊讶的是,他对架构设计的理解深度与广度,远在很多经验丰富的“老江湖”之上,并且已经完全形成了一套自己的方法论! 话说回来,那个小伙子要100k真一点也不多,现在高阶架构师这么缺,到哪他都抢手。 和他聊完后,我忍不住开始思考一个问题:为什么相同的工作经验、差不多的履历背景,人与人之间的差距,比人和猩猩的差距还要大?
80 0
阿里P8面试7分看能力,3分靠嘴皮,这份绝版Java面试神册.PDF
|
8月前
|
Dubbo NoSQL Java
震撼!阿里首次开源 Java 10万字题库,Github仅一天星标就超60K
众所周知“金三银四”是程序员找工作、跳槽最重要的月份。现在只剩下三个月的时间可以准备。随着行业的发展程序员面试也越来越难,面试中都是7分的能力,再加上3分的技巧; 对于应聘者,重中之重的就是简历,面试前一定要将最拿手和最能吸引面试官的技能在简历中展示出来;面试中,一定要有个平稳的心态,回答时要有条理、有头有尾,正确地回答面试官的问题,如果答错了也不要慌乱,坦然接受犯错,顺便虚心的请教面试官,能为下次面试做准备,也有很大的可能给面试官留下好印象,让面试官忽略你这个小失误;