5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)

简介: 5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)

前言


各位好,我是YourBatman。前面用四篇文章介绍完了Jackson底层流式API的读(JsonParser)、写(JsonGenerator)操作,我们清楚的知道,这哥俩都是abstract抽象类,使用时并没有显示的去new它们的(子类)实例,均通过一个工厂来搞定,这便就是本文的主角JsonFactory。


通过名称就知道,这是工厂设计模式。Jackson它并不建议你直接new读/写实例,因为那过于麻烦。为了对使用者屏蔽这些复杂的构造细节,于是就有了JsonFactory实例工厂的出现。


可能有的人会说,一个对象工厂有什么好了解的,很简单嘛。非也非也,一件事情本身的复杂度并不会凭空消失,而是从一个地方转移到另外一个地方,这另外一个地方指的就是JsonFactory。因此按照本系列的定位,了解它你绕不过去。


版本约定


  • Jackson版本:2.11.0
  • Spring Framework版本:5.2.6.RELEASE
  • Spring Boot版本:2.3.0.RELEASE


正文


JsonFactory是Jackson的(最)主要工厂类,用于 配置和构建JsonGenerator和JsonParser,这个工厂实例是线程安全的,因此可以重复使用。


作为一个实例工厂,它最重要的职责当然是创建实例对象。本工厂职责并不单一,它负责读、写两种实例的创建工作。


创建JsonGenerator实例

image.png


JsonGenerator它负责向目的地写数据,因此强调的是目的地在哪?如何写?


如截图所示,一共有六个重载方法用于构建JsonGenerator实例,多个重载方法目的是对使用者友好,我们可以认为最终效果是一样的。比如,底层实现是:


JsonFactory:
    @Override
    public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
        IOContext ctxt = _createContext(out, false);
        ctxt.setEncoding(enc);
    // 如果编码是UTF-8
        if (enc == JsonEncoding.UTF8) {
            return _createUTF8Generator(_decorate(out, ctxt), ctxt);
        }
        // 使用指定的编码把OutputStream包装为一个writer
        Writer w = _createWriter(out, enc, ctxt);
        return _createGenerator(_decorate(w, ctxt), ctxt);
    }


这就解释了,为何在详解JsonGenerator的这篇文章中,我一直以UTF8JsonGenerator作为实例进行讲解,因为例子中指定的编码就是UTF-8嘛。当然,即使你自己不显示的指定编码集,默认情况下Jackson也是使用UTF-8:



JsonFactory:
    @Override
    public JsonGenerator createGenerator(OutputStream out) throws IOException {
        return createGenerator(out, JsonEncoding.UTF8);
    }


示例:


@Test
public void test1() throws IOException {
    JsonFactory jsonFactory = new JsonFactory();
    JsonGenerator jsonGenerator1 = jsonFactory.createGenerator(System.out);
    JsonGenerator jsonGenerator2 = jsonFactory.createGenerator(System.out, JsonEncoding.UTF8);
    System.out.println(jsonGenerator1);
    System.out.println(jsonGenerator2);
}


运行程序,输出:

com.fasterxml.jackson.core.json.UTF8JsonGenerator@cb51256
com.fasterxml.jackson.core.json.UTF8JsonGenerator@59906517



创建JsonParser实例


image.png

JsonParser它负责从一个JSON字符串中提取出值,因此它强调的是数据从哪来?如何解析?


如截图所示,一共11个重载方法(其实最后一个不属于重载)用于构建JsonParser实例,它的底层实现是根据不同的数据媒介,使用了不同的处理方式,最终生成UTF8StreamJsonParser/ReaderBasedJsonParser。


你会发现这几个重载方法均无需我们指定编码集,那它是如何确定使用何种编码去解码形如byte[]数组这种数据来源的呢?这得益于其内部的编码自动发现机制实现,也就是ByteSourceJsonBootstrapper#detectEncoding()这个方法。


示例:


@Test
public void test2() throws IOException {
    JsonFactory jsonFactory = new JsonFactory();
    JsonParser jsonParser1 = jsonFactory.createParser("{}");
    // JsonParser jsonParser2 = jsonFactory.createParser(new FileReader("..."));
    JsonParser jsonParser3 = jsonFactory.createNonBlockingByteArrayParser();
    System.out.println(jsonParser1);
    // System.out.println(jsonParser2);
    System.out.println(jsonParser3);
}


运行程序,输出:

com.fasterxml.jackson.core.json.ReaderBasedJsonParser@5f3a4b84
com.fasterxml.jackson.core.json.async.NonBlockingJsonParser@27f723


创建非阻塞实例


值得注意的是,上面截图的11个方法中,最后一个并非重载。它创建的是一个非阻塞JSON解析器,也就是NonBlockingJsonParser,并且它还没有指定入参(数据源)。


NonBlockingJsonParser是Jackson在2.9版本新增的的一个解析器,目标是进一步提升效率、性能。但它也有局限的地方:只能解析使用UTF-8编码的内容,否则抛出异常


当然喽,现在UTF-8编码几乎成为了标准编码手段,问题不大。但是呢,我自己玩了玩NonBlockingJsonParser,发现复杂度增加不少(玩半天才玩明白😄),效果却并不显著,因此这里了解一下便可,至少目前不建议深入探究。


小贴士:不管是Spring还是Redis的反序列化,使用的均是普通的解析器(阻塞IO)。因为JSON解析过程从来都不会是性能瓶颈(特殊场景除外)



相关文章
|
JSON 安全 Java
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
一件事情本身的复杂度并不会凭空消失,而是从一个地方转移到另外一个地方
1132 0
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
|
设计模式 缓存 JavaScript
设计模式(二)—— 创建型模式|牛气冲天新年征文
设计模式(二)—— 创建型模式|牛气冲天新年征文
89 0
|
Web App开发 数据采集 JavaScript
前端周刊第二十六期
前端周刊发表每周前端技术相关的大事件、文章教程、一些框架的版本更新、以及代码和工具。每周定期发表,欢迎大家关注、转载。
前端周刊第二十六期
|
存储 Java 程序员
小白鼠带你啃Spring源码之BeanDifinition(二)
前言 文本已收录至我的GitHub仓库,欢迎Star:github.com/bin39232820… 种一棵树最好的时间是十年前,其次是现在
120 0
|
安全 Java 程序员
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
|
存储 JSON JavaScript
听说你情人节没人陪,这不我来给你介绍对象啦
听说你情人节没人陪,这不我来给你介绍对象啦
235 0
听说你情人节没人陪,这不我来给你介绍对象啦
|
存储 数据采集 运维
给工厂做开发,竟然喝着咖啡听“交响”?
给工厂做开发,竟然喝着咖啡听“交响”?云上不只有存储和计算,还有知识和经验。云计算提供的不只是一台一台的服务器,它提供给你的是丰富的知识和经验,你不光可以学习和使用,也可以基于这些知识经验去发展出属于你的新的知识和经验。”
744 0
给工厂做开发,竟然喝着咖啡听“交响”?
|
设计模式 Java
最全工厂设计模式案例详解,不服来辩!
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。
最全工厂设计模式案例详解,不服来辩!
|
设计模式 Java
最全工厂设计模式案例详解,不服来辩!(二)
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。
最全工厂设计模式案例详解,不服来辩!(二)
|
存储 JSON 缓存
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(中)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(中)