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,來看下面的示例:
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、更高級的配置
Jackson 之所以牛掰的一個很重要的因素是可以實現(xiàn)高度靈活的自定義配置。
在實際的應(yīng)用場景中,JSON 中常常會有一些 Java 對象中沒有的字段,這時候,如果直接解析的話,會拋出 UnrecognizedPropertyException 異常。
下面是一串 JSON 字符串:
String?jsonString?=?"{\n"?+ ????????????????"??\"name\"?:?\"沉默王二\",\n"?+ ????????????????"??\"age\"?:?18\n"?+ ????????????????"??\"sex\"?:?\"男\(zhòng)",\n"?+ ????????????????"}";
但 Java 對象 Writer 中沒有定義 sex 字段:
class?Writer{ ????private?String?name; ????private?int?age; ????//?getter/setter }
我們來嘗試解析一下:
ObjectMapper?mapper?=?new?ObjectMapper(); Writer?deserializedWriter?=?mapper.readValue(jsonString,?Writer.class);
不出意外,拋出異常了,sex 無法識別。
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"])
怎么辦呢?可以通過 configure()
方法忽略掉這些“無法識別”的字段。
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,?false);
除此之外,還有其他一些有用的配置信息,來了解一下:
//?在序列化時忽略值為?null?的屬性 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //?忽略值為默認(rèn)值的屬性 mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
04、處理日期格式
對于日期類型的字段,比如說 java.util.Date,如果不指定格式,序列化后將顯示為 long 類型的數(shù)據(jù),這種默認(rèn)格式的可讀性很差。
{ ??"age"?:?18, ??"birthday"?:?1606358621209 }
怎么辦呢?
第一種方案,在 getter 上使用 @JsonFormat
注解。
private?Date?birthday; //?GMT+8?是指格林尼治的標(biāo)準(zhǔn)時間,在加上八個小時表示你現(xiàn)在所在時區(qū)的時間 @JsonFormat(timezone?=?"GMT+8",?pattern?=?"yyyy-MM-dd?HH:mm:ss") public?Date?getBirthday()?{ ????return?birthday; } public?void?setBirthday(Date?birthday)?{ ????this.birthday?=?birthday; }
再來看一下結(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、字段過濾
在將 Java 對象序列化為 JSON 時,可能有些字段需要過濾,不顯示在 JSON 中,Jackson 有一種比較簡單的實現(xiàn)方式。
@JsonIgnore 用于過濾單個字段。
@JsonIgnore public?String?getName()?{ ????return?name; }
@JsonIgnoreProperties 用于過濾多個字段。
@JsonIgnoreProperties(value?=?{?"age","birthday"?}) class?Writer{ ????private?String?name; ????private?int?age; ????private?Date?birthday; }
06、自定義序列化和反序列化
當(dāng) Jackson 默認(rèn)序列化和反序列化不能滿足實際的開發(fā)需要時,可以自定義新的序列化和反序列化類。
自定義的序列化類需要繼承 StdSerializer,同時重寫 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)用它們,需要將其注冊到 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 中沒有添加 age 字段,所以只輸出了 name 字段。
再來看一下自定義的反序列化類,繼承 StdDeserializer,同時重寫 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>
通過 JsonNode 把 JSON 讀取到一個樹形結(jié)構(gòu)中,然后通過 JsonNode 的 get 方法將對應(yīng)字段讀取出來,然后生成新的 Java 對象,并返回。
定義好自定義反序列化類后,要想在程序中調(diào)用它們,同樣需要將其注冊到 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é)語
哎呀,好像不錯哦,Jackson 絕對配得上“最牛掰”這三個字,雖然有點虛。如果只想簡單的序列化和反序列化,使用 ObjectMapper 的 write 和 read 方法即可。
如果還想更進(jìn)一步的話,就需要對 ObjectMapper 進(jìn)行一些自定義配置,或者加一些注解,以及直接自定義序列化和反序列化類,更貼近一些 Java 對象。
需要注意的是,對日期格式的字段要多加小心,盡量不要使用默認(rèn)配置,可讀性很差。
好了,通過這篇文章的系統(tǒng)化介紹,相信你已經(jīng)完全摸透 Jackson 了,我們下篇文章見。
PS:如果你恰好需要一份 Java 精進(jìn)路線的話,我這里有一份,我差不多花了 3 天的時間整理的,還挺受歡迎的,已經(jīng) 2000 多贊了,每個階段都很詳細(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)

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.

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

Pre-formanceTartuptimeMoryusage, Quarkusandmicronautleadduetocompile-Timeprocessingandgraalvsupport, Withquarkusoftenperforminglightbetterine ServerLess scenarios.2.Thyvelopecosyste,

Java's garbage collection (GC) is a mechanism that automatically manages memory, which reduces the risk of memory leakage by reclaiming unreachable objects. 1.GC judges the accessibility of the object from the root object (such as stack variables, active threads, static fields, etc.), and unreachable objects are marked as garbage. 2. Based on the mark-clearing algorithm, mark all reachable objects and clear unmarked objects. 3. Adopt a generational collection strategy: the new generation (Eden, S0, S1) frequently executes MinorGC; the elderly performs less but takes longer to perform MajorGC; Metaspace stores class metadata. 4. JVM provides a variety of GC devices: SerialGC is suitable for small applications; ParallelGC improves throughput; CMS reduces

Networkportsandfirewallsworktogethertoenablecommunicationwhileensuringsecurity.1.Networkportsarevirtualendpointsnumbered0–65535,withwell-knownportslike80(HTTP),443(HTTPS),22(SSH),and25(SMTP)identifyingspecificservices.2.PortsoperateoverTCP(reliable,c

Gradleisthebetterchoiceformostnewprojectsduetoitssuperiorflexibility,performance,andmoderntoolingsupport.1.Gradle’sGroovy/KotlinDSLismoreconciseandexpressivethanMaven’sverboseXML.2.GradleoutperformsMaveninbuildspeedwithincrementalcompilation,buildcac

defer is used to perform specified operations before the function returns, such as cleaning resources; parameters are evaluated immediately when defer, and the functions are executed in the order of last-in-first-out (LIFO); 1. Multiple defers are executed in reverse order of declarations; 2. Commonly used for secure cleaning such as file closing; 3. The named return value can be modified; 4. It will be executed even if panic occurs, suitable for recovery; 5. Avoid abuse of defer in loops to prevent resource leakage; correct use can improve code security and readability.
