Alibaba 的fastjson源码详解

一、概述
Fastjson 是阿里巴巴开源的一个 Java 工具库,它常常被用来完成 Java 的对象与 JSON 格式的字符串的相互转化。
Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。

二、源码分析
1.首先以fastjson-1.2.70为例,用IDEA打开看下项目结构,如下:
在这里插入图片描述
2.涉及Java 的对象与 JSON 格式的字符串的相互转化,首先的分析JSON这个抽象类。
(1)这个类有很多的方法,如下图:
在这里插入图片描述
上述只是部分方法。

JSON类实现了2个接口,JSONStreamAware 、JSONAware。

JSONStreamAware :
其中writeJSONString方法 中的参数 Appendable 也是一个接口,也就是可以附加字符序列和值的对象,这个接口的作用是提供一个输出JSON字符串的方法,以便于其他的方法调用。

public interface JSONStreamAware {
    void writeJSONString(Appendable var1) throws IOException;
}

实现类:

   public void writeJSONString(Appendable appendable) {
        SerializeWriter out = new SerializeWriter();

        try {
            (new JSONSerializer(out)).write(this);
            appendable.append(out.toString());
        } catch (IOException var7) {
            throw new JSONException(var7.getMessage(), var7);
        } finally {
            out.close();
        }

    }

JSONAware:
这个接口只需要实现该接口的类实现toJSONString 的方法。

package com.alibaba.fastjson;

public interface JSONAware {
    String toJSONString();
}

具体实现:

    public String toJSONString() {
        SerializeWriter out = new SerializeWriter();

        String var2;
        try {
            (new JSONSerializer(out)).write(this);
            var2 = out.toString();
        } finally {
            out.close();
        }

        return var2;
    }

(2)JSON类中的方法。
JSON类重载大概有四类方法,分别为:

  • parse方法、parseObject方法、parseArray方法;返回结果分别为Object、JSONObject、JSONArray。
  • toJSONString方法,返回JSON字符串;toJSONBytes方法,返回byte数组
  • writeJSONString方法,将JSON写进write流
  • toJavaObject方法,将JSON对象转为java实体对象。

这个类中的四类方法是调用各个包中的方法。

这里主要说明我们经常使用的转换,parseObject 和 toJSONString,分别为转换为对象和JSON字符串。

第一个方法toJSONString,这个将java对象转换为JSON字符串:

String jsonStr = JSON.toJSONString(obj);

第一个方法parseObject ,这个将JSON字符串转换为java对象:

MyObject vo = JSON.parseObject(jsonStr, MyObject.class);

如果是返回对象是泛型,则可以这样转化。

import com.alibaba.fastjson.TypeReference;
List<MyObject> list = JSON.parseObject(jsonStr, new TypeReference<List<MyObject>>() {});

通过源码可以知道,JSONObject和JSONArray继承JSON。
JSONObject:

public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler {
    private static final long serialVersionUID = 1L;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    private final Map<String, Object> map;

    public JSONObject() {
        this(16, false);
    }

    public JSONObject(Map<String, Object> map) {
        if (map == null) {
            throw new IllegalArgumentException("map is null.");
        } else {
            this.map = map;
        }
    }

通过该类的继承与实现关系,可以发现,JSONObject实现了Map接口,而json对象中的数据都是以"键值对"形式出现,可以猜想, JSONObject底层操作是由Map实现的。

JSONArray:

public class JSONArray extends JSON implements List<Object>, Cloneable, RandomAccess, Serializable {
    private static final long serialVersionUID = 1L;
    private final List<Object> list;
    protected transient Object relatedArray;
    protected transient Type componentType;

    public JSONArray() {
        this.list = new ArrayList();
    }

    public JSONArray(List<Object> list) {
        if (list == null) {
            throw new IllegalArgumentException("list is null.");
        } else {
            this.list = list;
        }
    }

根据JSONArray的继承与实现,并结合上面对JSONObject的分析,可以发现,其内部是由List接口中的方法来完成操作的。

接着来看下JSON中的toJSONString()方法,它实现json对象转化为json字符串和java对象转化为json 字符串。

public static String toJSONString(Object object) {
        return toJSONString(object, emptyFilters);
    }

    public static String toJSONString(Object object, SerializerFeature... features) {
        return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
    }

    public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features) {
        SerializeWriter out = new SerializeWriter((Writer)null, defaultFeatures, features);

        String var5;
        try {
            JSONSerializer serializer = new JSONSerializer(out);
            serializer.write(object);
            var5 = out.toString();
        } finally {
            out.close();
        }

        return var5;
    }

该方法经过多次重载,但最终都是实现json对象转化为json字符串和java对象转化为json 字符串。

再来看下JSON类中的parseObject()方法,实现json字符串转换为json对象或javabean对象。

 public static JSONObject parseObject(String text, Feature... features) {
        return (JSONObject)parse(text, features);
    }

    public static JSONObject parseObject(String text) {
        Object obj = parse(text);
        if (obj instanceof JSONObject) {
            return (JSONObject)obj;
        } else {
            try {
                return (JSONObject)toJSON(obj);
            } catch (RuntimeException var3) {
                throw new JSONException("can not cast to JSONObject.", var3);
            }
        }
    }

该方法返回JSONObject对象,用于实现json字符串向json对象的转化,其内部调用了parse()方法,调用底层的DefaultJSONParser解析类进行转化,在转化失败时,抛出异常。

最后就是JSON类中的JSONArray()方法,实现json字符串转化为json对象数组或List。

 public static JSONArray parseArray(String text) {
        if (text == null) {
            return null;
        } else {
            DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance());
            JSONLexer lexer = parser.lexer;
            JSONArray array;
            if (lexer.token() == 8) {
                lexer.nextToken();
                array = null;
            } else if (lexer.token() == 20) {
                array = null;
            } else {
                array = new JSONArray();
                parser.parseArray(array);
                parser.handleResovleTask(array);
            }

            parser.close();
            return array;
        }
    }

这个与parseObject()方法类似。

(3)我们可以通过main方法测试下:

public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("name","张三");
        map.put("age",20);

        System.out.println("----javaBean  to jsonString-------");
        String str1= JSON.toJSONString(map);
        System.out.println("str1:"+str1);

        System.out.println("-----jsonString to javaBean------");
        //Map map1=JSON.parseObject(str1,new TypeReference<Map>(){});
        Map map1=JSON.parseObject(str1,Map.class);
        System.out.println(map1);
        System.out.println("map1:"+map1);

        List<Map<String,Object>> list = new ArrayList<>();
        list.add(map);
        System.out.println("-----jsonString to jsonArray-----");
        List<Map> list1=JSON.parseArray(JSON.toJSONString(list),Map.class);

        System.out.println("list1:"+list1);

    }

打印结果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/572004.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nodejs

334 先下载zip文件&#xff0c;然后加上.zip,可以看到两个文件 在user中可以看到 输入即可得到flag。 335. 这里提到eval函数&#xff0c;eval中可以执行js代码&#xff0c;可以尝试使用这个函数进行测试 payload&#xff08;显示当前目录下的文件和文件夹列表&#xff09; …

基于emp的mysql查询

SQL命令 结构化查询语句&#xff1a;Structured Query Language 结构化查询语言是高级的非过程化变成语言&#xff0c;允许用户在高层数据结构上工作。是一种特殊目的的变成语言&#xff0c;是一种数据库查询和程序设计语言&#xff0c;用于存取数据以及查询、更新和管理关系数…

Python 网络与并发编程(四)

文章目录 协程Coroutines协程的核心(控制流的让出和恢复)协程和多线程比较协程的优点协程的缺点 asyncio实现协程(重点) 协程Coroutines 协程&#xff0c;全称是“协同程序”&#xff0c;用来实现任务协作。是一种在线程中&#xff0c;比线程更加轻量级的存在&#xff0c;由程…

android脱壳第二发:grpc-dumpdex加修复

上一篇我写的dex脱壳&#xff0c;写到银行类型的app的dex修复问题&#xff0c;因为dex中被抽取出来的函数的code_item_off 的偏移所在的内存&#xff0c;不在dex文件范围内&#xff0c;所以需要进行一定的修复&#xff0c;然后就停止了。本来不打算接着搞得&#xff0c;但是写了…

基础SQL DCL语句

DCL是数据控制语言&#xff0c;用来管理数据库用户&#xff0c;还有控制用户的访问权限 1.用户的查询 MySQL的用户信息存储在mysql数据库中&#xff0c;查询用户时&#xff0c;我们需要使用这个数据库。 后面&#xff0c;还有很多数据&#xff0c;因为篇幅的问题&#xff0c;就…

【FFmpeg】音视频录制 ② ( 使用 Screen Capturer Recorder 软件生成 ffmpeg 可录制的音视频设备 )

文章目录 一、使用 Screen Capturer Recorder 软件生成音视频设备1、设备查找问题 - 引入 Screen Capturer Recorder 软件2、下载安装 Screen Capturer Recorder 软件3、验证 Screen Capturer Recorder 生成的设备 一、使用 Screen Capturer Recorder 软件生成音视频设备 1、设…

【PyTorch】torch.gather() 用法

gather常被用于image做mask的操作中&#xff0c;对哪些地方进行赋值0/1 API&#xff1a; torch.gather — PyTorch 2.2 documentation torch.gather(input, dim, index, outNone) → Tensor gather()的意义&#xff1a; 顾名思义&#xff0c;聚集、集合&#xff1a;gather…

在mac上安装node.js及使用npm,yarn相关命令教程

1、安装node.js 官网&#xff1a;Node.js — Download Node.js 选择需要的版本&#xff0c;点击DownLoad 2、点击继续&#xff0c;直到安装成功。 2.1打开终端输入命令node -v 显示版本号则说明已安装成功 3、全局安装yarn命令 1、sudo npm install --global yarn &#xf…

Python构建学生信息管理系统:构建RESTful API - 学生信息管理系统的后端逻辑

在之前的博客里&#xff0c;我们已经完成了项目初始化&#xff0c;在本篇博客中&#xff0c;我们将深入探讨如何使用Flask框架实现学生信息管理系统的后端逻辑&#xff0c;特别是通过RESTful API来实现学生信息的增删改查&#xff08;CRUD&#xff09;操作。 Flask RESTful AP…

计网笔记:第1章 计算机网络概论

计网笔记&#xff1a;第1章 计算机网络概论 第1章 计算机网络概论1.1 计算机网络发展与分类1.2 OSI和TCP/IP参考模型OSI与TCP/IP参考模型图 1.3 数据封装与解封过程借助OSI模型理解数据传输过程(封装)借助OSI模型理解数据传输过程(解封) 1.4 本章例题 第1章 计算机网络概论 1.…

详解Al作画算法原理

ChatGPT AI作画算法&#xff0c;又称为AI图像生成算法&#xff0c;是一种人工智能技术&#xff0c;它可以根据给定的输入自动生成图像。这类算法近年来变得非常流行&#xff0c;尤其是随着深度学习技术的发展。这里我将聚焦于目前最先进的一类AI作画算法&#xff0c;即生成对抗…

PHP定期给自己网站目录做个特征镜像供快速对比

效果图 上代码&#xff1a; <style> h1{font-size:24px;line-height:180%;font-weight:600;margin:1px 2px;color:#0180cf;} h2{font-size:20px;line-height:140%;font-weight:600;margin:2px 4px;color:green;} h3{font-size:16px;line-height:140%;font-weight:600;m…

Hive——DML(Data Manipulation Language)数据操作语句用法详解

DML 1.Load Load语句可将文件导入到Hive表中。 hive> LOAD DATA [LOCAL] INPATH filepath [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1val1, partcol2val2 ...)];关键字说明&#xff1a; local&#xff1a;表示从本地加载数据到Hive表&#xff1b;否则从HD…

react实现时钟翻牌效果

需求&#xff1a;随着数字的变动要求有时钟翻动动效 问题&#xff1a;只在加载时有动效 解决方案&#xff1a;通过判断数字改变&#xff08;这里通过新旧数值变动来判断&#xff0c;不贴代码啦&#xff09;&#xff0c;每次变动的时候手动把animationIterationCount设置为inf…

linux安装MySQL8.0,密码修改权限配置等常规操作详解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

python爬虫之xpath4

1 最终项目实现的代码 仙剑 #!/usr/bin/env python ​ import logging import requests import re from urllib.parse import urljoin import pymongo import multiprocessing ​ mongo_client pymongo.MongoClient("mongodb://192.168.135.131:27017/") db mong…

短视频评论ID批量爬虫提取获客软件|视频评论下载采集工具

短视频评论批量抓取软件&#xff1a;智能拓客&#xff0c;精准抓取用户反馈 主要功能一览 1. 智能抓取任务创建&#xff1a; 软件提供了任务创建功能&#xff0c;用户只需输入任务名称、搜索关键词以及评论监控词&#xff0c;即可开始智能抓取。不仅能够搜索关键词匹配的视频…

【学习记录】autoware标定相机与激光雷达外参

一、autoware选择 这里踩了好几个坑&#xff0c;首先autoware作为一个无人驾驶知名框架&#xff0c;其内部实际上是有两套标定的东西的&#xff0c;这一点绝大多数博客没有提到。其中最常用的是一个叫标定工具箱的东西&#xff0c;这个ros包已经在1.10往后的版本中被删掉了&am…

全彩屏负氧离子监测站的使用

TH-FZ5在繁忙的都市生活中&#xff0c;我们往往忽视了一个至关重要的问题——空气质量。随着工业化的进程加速&#xff0c;空气污染已成为影响人们健康的一大隐患。为了实时监测和了解身边的空气质量&#xff0c;全彩屏负氧离子监测站应运而生&#xff0c;成为了我们守护呼吸健…