The Java JSON parser that I think is the best: Jackson
Dec 16, 2020 am 09:48 AMjava basic tutorialThe column introduces the Java JSON parser
Recommended (Free): Java Basics Tutorial
In today’s programming world, JSON has become the preferred protocol for transmitting information from the client to the server. It is no exaggeration to say that XML is the former wave that was photographed dead on the beach.
Unfortunately, JDK does not have a JSON library. I don’t know why I don’t work on it. At the time of Log4j, java.util.logging was also launched in order to compete, although in the end not many people used it.
The reason why Java is awesome is that its ecology is very complete. JDK does not have a JSON library, but third-party libraries do, which are quite good. For example, the pig's feet in this article - Jackson, GitHub star 6.1k, Spring Boot's default JSON parser.
How to prove this?
When we create a new Spring Boot Web project through starter, we can see Jackson in the Maven dependencies.
Jackson has many advantages:
- It is faster to parse large files;
- It takes up less memory when running , better performance;
- API is very flexible and easy to expand and customize.
Jackson's core module consists of three parts:
- jackson-core, the core package, provides related APIs based on "stream mode" parsing, including JsonPaser and JsonGenerator.
- jackson-annotations, annotation package, provides standard annotation functions;
- jackson-databind, data binding package, provides related APIs (ObjectMapper) based on "object binding" parsing and Related API for "tree model" parsing (JsonNode).
01. Introducing Jackson dependencies
To use Jackson, you need to add Jackson dependencies in the pom.xml file.
<dependency> ????<groupid>com.fasterxml.jackson.core</groupid> ????<artifactid>jackson-databind</artifactid> ????<version>2.10.1</version> </dependency>
jackson-databind depends on jackson-core and jackson-annotations, so after adding jackson-databind, Maven will automatically introduce jackson-core and jackson-annotations into the project.
The reason why Maven is so lovable is that it can secretly help us do what we need to do.
02. Use ObjectMapper
Jackson’s most commonly used API is ObjectMapper based on “object binding”. It serializes Java objects into JSON through a series of writeValue methods, and can store them in different format.
-
writeValueAsString(Object value)
method, stores the object as a string -
writeValueAsBytes(Object value)
method, stores the object Into a byte array -
writeValue(File resultFile, Object value)
method, store the object as a file
Let’s take a look at the code example of storing it as a string :
import?com.fasterxml.jackson.core.JsonProcessingException; import?com.fasterxml.jackson.databind.ObjectMapper; /** ?*?微信搜索「沉默王二」,回復(fù)?Java ?* ?*?@author?沉默王二 ?*?@date?2020/11/26 ?*/ public?class?Demo?{ ????public?static?void?main(String[]?args)?throws?JsonProcessingException?{ ????????Writer?wanger?=?new?Writer("沉默王二",?18); ????????ObjectMapper?mapper?=?new?ObjectMapper(); ????????String?jsonString?=?mapper.writerWithDefaultPrettyPrinter() ????????????????.writeValueAsString(wanger); ????????System.out.println(jsonString); ????} } class?Writer?{ ????private?String?name; ????private?int?age; ????public?Writer(String?name,?int?age)?{ ????????this.name?=?name; ????????this.age?=?age; ????} ????public?String?getName()?{ ????????return?name; ????} ????public?void?setName(String?name)?{ ????????this.name?=?name; ????} ????public?int?getAge()?{ ????????return?age; ????} ????public?void?setAge(int?age)?{ ????????this.age?=?age; ????} }
The program output result is as follows:
{ ??"name"?:?"沉默王二", ??"age"?:?18 }
Not all fields support serialization and deserialization and need to comply with the following rules:
- If If the modifier of the field is public, the field can be serialized and deserialized (not standard writing).
- If the modifier of a field is not public, but its getter method and setter method are public, the field can be serialized and deserialized. The getter method is used for serialization and the setter method is used for deserialization.
- If a field only has a public setter method but no public getter method, the field can only be used for deserialization.
If you want to change the default serialization and deserialization rules, you need to call the setVisibility()
method of ObjectMapper. Otherwise, an InvalidDefinitionException will be thrown.
ObjectMapper deserializes JSON into Java objects from different data sources through the readValue series of methods.
-
readValue(String content, Class<t> valueType)</t>
method, deserializes the string into a Java object -
readValue(byte[ ] src, Class<t> valueType)</t>
method, deserializes the byte array into a Java object -
readValue(File src, Class<t> valueType)</t>
method, deserializes the byte array into a Java object Deserializing files into Java objects
Let’s take a look at the code example of deserializing strings into Java objects:
import?com.fasterxml.jackson.core.JsonProcessingException; import?com.fasterxml.jackson.databind.ObjectMapper; /** ?*?微信搜索「沉默王二」,回復(fù)?Java ?* ?*?@author?沉默王二 ?*?@date?2020/11/26 ?*/ public?class?Demo?{ ????public?static?void?main(String[]?args)?throws?JsonProcessingException?{ ????????ObjectMapper?mapper?=?new?ObjectMapper(); ????????String?jsonString?=?"{\n"?+ ????????????????"??\"name\"?:?\"沉默王二\",\n"?+ ????????????????"??\"age\"?:?18\n"?+ ????????????????"}"; ????????Writer?deserializedWriter?=?mapper.readValue(jsonString,?Writer.class); ????????System.out.println(deserializedWriter); ????} } class?Writer{ ????private?String?name; ????private?int?age; ????//?getter/setter ????@Override ????public?String?toString()?{ ????????return?"Writer{"?+ ????????????????"name='"?+?name?+?'\''?+ ????????????????",?age="?+?age?+ ????????????????'}'; ????} }
The program output is as follows:
Writer{name='沉默王二',?age=18}
PS: If the deserialized object has a constructor with parameters, it must have an empty default constructor, otherwise an InvalidDefinitionException
line will be thrown.
Exception?in?thread?"main"?com.fasterxml.jackson.databind.exc.InvalidDefinitionException:?Cannot?construct?instance?of?`com.itwanger.jackson.Writer`?(no?Creators,?like?default?construct,?exist):?cannot?deserialize?from?Object?value?(no?delegate-?or?property-based?Creator) ?at?[Source:?(String)"{ ??"name"?:?"沉默王二", ??"age"?:?18 }";?line:?2,?column:?3] ????at?com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ????at?com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589) ????at?com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1055) ????at?com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) ????at?com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) ????at?com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ????at?com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) ????at?com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205) ????at?com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173) ????at?com.itwanger.jackson.Demo.main(Demo.java:19)
Jackson's most commonly used API is ObjectMapper based on "object binding".
ObjectMapper can also parse JSON into JsonNode objects based on "tree model", see the example below.
import?com.fasterxml.jackson.core.JsonProcessingException; import?com.fasterxml.jackson.databind.JsonNode; import?com.fasterxml.jackson.databind.ObjectMapper; /** ?*?微信搜索「沉默王二」,回復(fù)?Java ?* ?*?@author?沉默王二 ?*?@date?2020/11/26 ?*/ public?class?JsonNodeDemo?{ ????public?static?void?main(String[]?args)?throws?JsonProcessingException?{ ????????ObjectMapper?mapper?=?new?ObjectMapper(); ????????String?json?=?"{?\"name\"?:?\"沉默王二\",?\"age\"?:?18?}"; ????????JsonNode?jsonNode?=?mapper.readTree(json); ????????String?name?=?jsonNode.get("name").asText(); ????????System.out.println(name);?//?沉默王二 ????} }
借助 TypeReference 可以將 JSON 字符串?dāng)?shù)組轉(zhuǎn)成泛型 List,來(lái)看下面的示例:
import?com.fasterxml.jackson.core.JsonProcessingException; import?com.fasterxml.jackson.core.type.TypeReference; import?com.fasterxml.jackson.databind.ObjectMapper; import?java.util.List; /** ?*?微信搜索「沉默王二」,回復(fù)?Java ?* ?*?@author?沉默王二 ?*?@date?2020/11/26 ?*/ public?class?TypeReferenceDemo?{ ????public?static?void?main(String[]?args)?throws?JsonProcessingException?{ ????????ObjectMapper?mapper?=?new?ObjectMapper(); ????????String?json?=?"[{?\"name\"?:?\"沉默王三\",?\"age\"?:?18?},?{?\"name\"?:?\"沉默王二\",?\"age\"?:?19?}]"; ????????List<author>?listAuthor?=?mapper.readValue(json,?new?TypeReference<list>>(){}); ????????System.out.println(listAuthor); ????} } class?Author{ ????private?String?name; ????private?int?age; ????//?getter/setter ????//?toString }</list></author>
03、更高級(jí)的配置
Jackson 之所以牛掰的一個(gè)很重要的因素是可以實(shí)現(xiàn)高度靈活的自定義配置。
在實(shí)際的應(yīng)用場(chǎng)景中,JSON 中常常會(huì)有一些 Java 對(duì)象中沒(méi)有的字段,這時(shí)候,如果直接解析的話,會(huì)拋出 UnrecognizedPropertyException 異常。
下面是一串 JSON 字符串:
String?jsonString?=?"{\n"?+ ????????????????"??\"name\"?:?\"沉默王二\",\n"?+ ????????????????"??\"age\"?:?18\n"?+ ????????????????"??\"sex\"?:?\"男\(zhòng)",\n"?+ ????????????????"}";
但 Java 對(duì)象 Writer 中沒(méi)有定義 sex 字段:
class?Writer{ ????private?String?name; ????private?int?age; ????//?getter/setter }
我們來(lái)嘗試解析一下:
ObjectMapper?mapper?=?new?ObjectMapper(); Writer?deserializedWriter?=?mapper.readValue(jsonString,?Writer.class);
不出意外,拋出異常了,sex 無(wú)法識(shí)別。
Exception?in?thread?"main"?com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:?Unrecognized?field?"sex"?(class?com.itwanger.jackson.Writer),?not?marked?as?ignorable?(2?known?properties:?"name",?"age"]) ?at?[Source:?(String)"{ ??"name"?:?"沉默王二", ??"age"?:?18, ??"sex"?:?"男" }";?line:?4,?column:?12]?(through?reference?chain:?com.itwanger.jackson.Writer["sex"])
怎么辦呢?可以通過(guò) configure()
方法忽略掉這些“無(wú)法識(shí)別”的字段。
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,?false);
除此之外,還有其他一些有用的配置信息,來(lái)了解一下:
//?在序列化時(shí)忽略值為?null?的屬性 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //?忽略值為默認(rèn)值的屬性 mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
04、處理日期格式
對(duì)于日期類型的字段,比如說(shuō) java.util.Date,如果不指定格式,序列化后將顯示為 long 類型的數(shù)據(jù),這種默認(rèn)格式的可讀性很差。
{ ??"age"?:?18, ??"birthday"?:?1606358621209 }
怎么辦呢?
第一種方案,在 getter 上使用 @JsonFormat
注解。
private?Date?birthday; //?GMT+8?是指格林尼治的標(biāo)準(zhǔn)時(shí)間,在加上八個(gè)小時(shí)表示你現(xiàn)在所在時(shí)區(qū)的時(shí)間 @JsonFormat(timezone?=?"GMT+8",?pattern?=?"yyyy-MM-dd?HH:mm:ss") public?Date?getBirthday()?{ ????return?birthday; } public?void?setBirthday(Date?birthday)?{ ????this.birthday?=?birthday; }
再來(lái)看一下結(jié)果:
{ ??"age"?:?18, ??"birthday"?:?"2020-11-26?03:02:30" }
具體代碼如下所示:
ObjectMapper?mapper?=?new?ObjectMapper(); Writer?wanger?=?new?Writer("沉默王二",?18); wanger.setBirthday(new?Date()); String?jsonString?=?mapper.writerWithDefaultPrettyPrinter() ????????????????.writeValueAsString(wanger); System.out.println(jsonString);
第二種方案,調(diào)用 ObjectMapper 的 setDateFormat()
方法。
ObjectMapper?mapper?=?new?ObjectMapper(); mapper.setDateFormat(StdDateFormat.getDateTimeInstance()); Writer?wanger?=?new?Writer("沉默王二",?18); wanger.setBirthday(new?Date()); String?jsonString?=?mapper.writerWithDefaultPrettyPrinter() ????????????????.writeValueAsString(wanger); System.out.println(jsonString);
輸出結(jié)果如下所示:
{ ??"name"?:?"沉默王二", ??"age"?:?18, ??"birthday"?:?"2020年11月26日?上午11:09:51" }
05、字段過(guò)濾
在將 Java 對(duì)象序列化為 JSON 時(shí),可能有些字段需要過(guò)濾,不顯示在 JSON 中,Jackson 有一種比較簡(jiǎn)單的實(shí)現(xiàn)方式。
@JsonIgnore 用于過(guò)濾單個(gè)字段。
@JsonIgnore public?String?getName()?{ ????return?name; }
@JsonIgnoreProperties 用于過(guò)濾多個(gè)字段。
@JsonIgnoreProperties(value?=?{?"age","birthday"?}) class?Writer{ ????private?String?name; ????private?int?age; ????private?Date?birthday; }
06、自定義序列化和反序列化
當(dāng) Jackson 默認(rèn)序列化和反序列化不能滿足實(shí)際的開(kāi)發(fā)需要時(shí),可以自定義新的序列化和反序列化類。
自定義的序列化類需要繼承 StdSerializer,同時(shí)重寫(xiě) serialize()
方法,利用 JsonGenerator 生成 JSON,示例如下:
/** ?*?微信搜索「沉默王二」,回復(fù)?Java ?* ?*?@author?沉默王二 ?*?@date?2020/11/26 ?*/ public?class?CustomSerializer?extends?StdSerializer<man>?{ ????protected?CustomSerializer(Class<man>?t)?{ ????????super(t); ????} ????public?CustomSerializer()?{ ????????this(null); ????} ????@Override ????public?void?serialize(Man?value,?JsonGenerator?gen,?SerializerProvider?provider)?throws?IOException?{ ????????gen.writeStartObject(); ????????gen.writeStringField("name",?value.getName()); ????????gen.writeEndObject(); ????} } class?Man{ ????private?int?age; ????private?String?name; ????public?Man(int?age,?String?name)?{ ????????this.age?=?age; ????????this.name?=?name; ????} ????public?int?getAge()?{ ????????return?age; ????} ????public?void?setAge(int?age)?{ ????????this.age?=?age; ????} ????public?String?getName()?{ ????????return?name; ????} ????public?void?setName(String?name)?{ ????????this.name?=?name; ????} }</man></man>
定義好自定義序列化類后,要想在程序中調(diào)用它們,需要將其注冊(cè)到 ObjectMapper 的 Module 中,示例如下所示:
ObjectMapper?mapper?=?new?ObjectMapper(); SimpleModule?module?= ????????new?SimpleModule("CustomSerializer",?new?Version(1,?0,?0,?null,?null,?null)); module.addSerializer(Man.class,?new?CustomSerializer()); mapper.registerModule(module); Man?man?=?new?Man(?18,"沉默王二"); String?json?=?mapper.writeValueAsString(man); System.out.println(json);
程序輸出結(jié)果如下所示:
{"name":"沉默王二"}
自定義序列化類 CustomSerializer 中沒(méi)有添加 age 字段,所以只輸出了 name 字段。
再來(lái)看一下自定義的反序列化類,繼承 StdDeserializer,同時(shí)重寫(xiě) deserialize()
方法,利用 JsonGenerator 讀取 JSON,示例如下:
public?class?CustomDeserializer?extends?StdDeserializer<woman>?{ ????protected?CustomDeserializer(Class>?vc)?{ ????????super(vc); ????} ????public?CustomDeserializer()?{ ????????this(null); ????} ????@Override ????public?Woman?deserialize(JsonParser?p,?DeserializationContext?ctxt)?throws?IOException,?JsonProcessingException?{ ????????JsonNode?node?=?p.getCodec().readTree(p); ????????Woman?woman?=?new?Woman(); ????????int?age?=?(Integer)?((IntNode)?node.get("age")).numberValue(); ????????String?name?=?node.get("name").asText(); ????????woman.setAge(age); ????????woman.setName(name); ????????return?woman; ????} } class?Woman{ ????private?int?age; ????private?String?name; ????public?Woman()?{ ????} ????//?getter/setter ????@Override ????public?String?toString()?{ ????????return?"Woman{"?+ ????????????????"age="?+?age?+ ????????????????",?name='"?+?name?+?'\''?+ ????????????????'}'; ????} }</woman>
通過(guò) JsonNode 把 JSON 讀取到一個(gè)樹(shù)形結(jié)構(gòu)中,然后通過(guò) JsonNode 的 get 方法將對(duì)應(yīng)字段讀取出來(lái),然后生成新的 Java 對(duì)象,并返回。
定義好自定義反序列化類后,要想在程序中調(diào)用它們,同樣需要將其注冊(cè)到 ObjectMapper 的 Module 中,示例如下所示:
ObjectMapper?mapper?=?new?ObjectMapper(); SimpleModule?module?= ????????new?SimpleModule("CustomDeserializer",?new?Version(1,?0,?0,?null,?null,?null)); module.addDeserializer(Woman.class,?new?CustomDeserializer()); mapper.registerModule(module); String?json?=?"{?\"name\"?:?\"三妹\",?\"age\"?:?18?}"; Woman?woman?=?mapper.readValue(json,?Woman.class); System.out.println(woman);
程序輸出結(jié)果如下所示:
Woman{age=18,?name='三妹'}
07、結(jié)語(yǔ)
哎呀,好像不錯(cuò)哦,Jackson 絕對(duì)配得上“最牛掰”這三個(gè)字,雖然有點(diǎn)虛。如果只想簡(jiǎn)單的序列化和反序列化,使用 ObjectMapper 的 write 和 read 方法即可。
如果還想更進(jìn)一步的話,就需要對(duì) ObjectMapper 進(jìn)行一些自定義配置,或者加一些注解,以及直接自定義序列化和反序列化類,更貼近一些 Java 對(duì)象。
需要注意的是,對(duì)日期格式的字段要多加小心,盡量不要使用默認(rèn)配置,可讀性很差。
好了,通過(guò)這篇文章的系統(tǒng)化介紹,相信你已經(jīng)完全摸透 Jackson 了,我們下篇文章見(jiàn)。
PS:如果你恰好需要一份 Java 精進(jìn)路線的話,我這里有一份,我差不多花了 3 天的時(shí)間整理的,還挺受歡迎的,已經(jīng) 2000 多贊了,每個(gè)階段都很詳細(xì)。
相關(guān)免費(fèi)學(xué)習(xí)推薦:php編程(視頻)
The above is the detailed content of The Java JSON parser that I think is the best: Jackson. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

The settings.json file is located in the user-level or workspace-level path and is used to customize VSCode settings. 1. User-level path: Windows is C:\Users\\AppData\Roaming\Code\User\settings.json, macOS is /Users//Library/ApplicationSupport/Code/User/settings.json, Linux is /home//.config/Code/User/settings.json; 2. Workspace-level path: .vscode/settings in the project root directory

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

DependencyInjection(DI)isadesignpatternwhereobjectsreceivedependenciesexternally,promotingloosecouplingandeasiertestingthroughconstructor,setter,orfieldinjection.2.SpringFrameworkusesannotationslike@Component,@Service,and@AutowiredwithJava-basedconfi

itertools.combinations is used to generate all non-repetitive combinations (order irrelevant) that selects a specified number of elements from the iterable object. Its usage includes: 1. Select 2 element combinations from the list, such as ('A','B'), ('A','C'), etc., to avoid repeated order; 2. Take 3 character combinations of strings, such as "abc" and "abd", which are suitable for subsequence generation; 3. Find the combinations where the sum of two numbers is equal to the target value, such as 1 5=6, simplify the double loop logic; the difference between combinations and arrangement lies in whether the order is important, combinations regard AB and BA as the same, while permutations are regarded as different;

java.lang.OutOfMemoryError: Javaheapspace indicates insufficient heap memory, and needs to check the processing of large objects, memory leaks and heap settings, and locate and optimize the code through the heap dump analysis tool; 2. Metaspace errors are common in dynamic class generation or hot deployment due to excessive class metadata, and MaxMetaspaceSize should be restricted and class loading should be optimized; 3. Unabletocreatenewnativethread due to exhausting system thread resources, it is necessary to check the number of threads, use thread pools, and adjust the stack size; 4. GCoverheadlimitexceeded means that GC is frequent but has less recycling, and GC logs should be analyzed and optimized.

fixture is a function used to provide preset environment or data for tests. 1. Use the @pytest.fixture decorator to define fixture; 2. Inject fixture in parameter form in the test function; 3. Execute setup before yield, and then teardown; 4. Control scope through scope parameters, such as function, module, etc.; 5. Place the shared fixture in conftest.py to achieve cross-file sharing, thereby improving the maintainability and reusability of tests.

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear
