欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Jackson解決Json序列化和反序列化問題

 更新時間:2023年05月26日 14:20:16   作者:衍志  
Jackson是一個用于處理Json數(shù)據(jù)的Java庫,它提供了一系列功能,包括Json序列化和反序列化,所以本文就來講講如何利用利用Jackson解決Json序列化和反序列化的問題吧

前言

在前后端分離的應(yīng)用中,前端往往需要向后端發(fā)送命令請求,并將請求中的數(shù)據(jù)以Json格式傳遞。后端需要將Json格式的數(shù)據(jù)反序列化成Java對象,以便進行處理。但是,在實際應(yīng)用中,我們會遇到一些挑戰(zhàn),比如多態(tài)類型處理的需求,以及需要將多個API壓縮成一個API等。本文將介紹如何使用Jackson庫解決這些問題。

Jackson庫簡介

Jackson庫概述

Jackson是一個用于處理Json數(shù)據(jù)的Java庫,由FasterXML開發(fā)和維護。它提供了一系列功能,包括Json序列化和反序列化、Json樹模型、流式API等。

Jackson主要特性

  • 支持Java對象與Json之間的轉(zhuǎn)換
  • 支持Json樹模型
  • 支持流式API
  • 支持注解,靈活地控制序列化和反序列化過程
  • 支持多態(tài)類型處理

JsonTypeInfo和JsonSubTypes的基本概念

JsonTypeInfo的作用與使用場景

在進行Json序列化和反序列化時,我們需要考慮Java對象的類型信息,以便正確地將Json數(shù)據(jù)轉(zhuǎn)換成Java對象。JsonTypeInfo提供了一種機制,用于在序列化和反序列化時處理Java對象的類型信息。

JsonSubTypes的作用與使用場景

JsonSubTypes是JsonTypeInfo的一個子注解,用于指定Java類的子類。當我們需要序列化和反序列化一個包含多態(tài)類型的Java對象時,我們可以使用@JsonTypeInfo和@JsonSubTypes注解來指定子類的類型信息。

實際應(yīng)用案例

代碼示例:動物園

假設(shè)我們有一個動物園,里面有各種動物,包括狗、貓、魚等。我們需要將動物園中的動物序列化成Json格式,并將其發(fā)送到前端。我們定義一個Animal類作為父類,然后定義三個子類:Dog、Cat和Fish。具體代碼如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Fish.class, name = "fish")
})
public abstract class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class Dog extends Animal {
    private String breed;
    public Dog(String name, String breed) {
        super(name);
        this.breed = breed;
    }
    public String getBreed() {
        return breed;
    }
    public void setBreed(String breed) {
        this.breed = breed;
    }
}
public class Cat extends Animal {
    private String color;
    public Cat(String name, String color) {
        super(name);
        this.color = color;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
}
public class Fish extends Animal {
    private String species;
    public Fish(String name, String species) {
        super(name);
        this.species = species;
    }
    public String getSpecies() {
        return species;
    }
    public void setSpecies(String species) {
        this.species = species;
    }
}

從父類到子類的序列化和反序列化

現(xiàn)在我們需要將動物園中的所有動物序列化成Json格式。我們可以使用ObjectMapper類的writeValueAsString()方法來實現(xiàn)。具體代碼如下:

List<Animal> animals = new ArrayList<>();
animals.add(new Dog("旺財", "金毛"));
animals.add(new Cat("小花", "黑白"));
animals.add(new Fish("尼莫", "小丑魚"));
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(animals);

反之,我們可以使用ObjectMapper類的readValue()方法將Json數(shù)據(jù)反序列化成Java對象。具體代碼如下:

List<Animal> animals = objectMapper.readValue(json, new TypeReference<List<Animal>>() {});

自定義類型信息屬性

我們可以通過@JsonTypeInfo注解的property屬性來自定義類型信息的屬性名。例如,我們將property屬性的值設(shè)置為"animalType",則Json數(shù)據(jù)中的類型信息屬性名也會變?yōu)?quot;animalType"。具體代碼如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "animalType")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Fish.class, name = "fish")
})
public abstract class Animal {
    ...
}

好的,以下是使用markdown的翻譯和例子:

JsonTypeInfo類

JsonTypeInfo類是一個注解,用于配置在JSON序列化和反序列化中使用類型信息的詳細信息,以保留有關(guān)對象實例的實際類的信息。這對于多態(tài)類型是必需的,并且還可能需要鏈接抽象聲明類型和匹配的具體實現(xiàn)。

參數(shù)方法

JsonTypeInfo類的參數(shù)方法如下:

use:定義如何使用類型信息。有三個選項:Id.CLASS,Id.NAMEId.MINIMAL_CLASS。默認值為Id.CLASS。

include:定義類型信息的包含方式。有四個選項:As.PROPERTYAs.WRAPPER_OBJECT,As.EXISTING_PROPERTYAs.EXTERNAL_PROPERTY。默認值為As.PROPERTY。

property:定義包含類型信息的屬性的名稱。默認值為"$type"。

例子

以下是使用JsonTypeInfo類的一些例子:

// 將Java類名("com.myempl.ImplClass")包含在JSON屬性"class"中
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "class")
// 將邏輯類型名稱(在實現(xiàn)類中定義)作為包裝器包含;2個注釋
@JsonTypeInfo(use = Id.NAME, include = As.WRAPPER_OBJECT)
@JsonSubTypes({
    @JsonSubTypes.Type(value = com.myemp.Impl1.class, name = "impl1"),
    @JsonSubTypes.Type(value = com.myempl.Impl2.class, name = "impl2")
})

在第一個例子中,use參數(shù)設(shè)置為Id.CLASS,這意味著使用Java類名作為類型信息。include參數(shù)設(shè)置為As.PROPERTY,這意味著類型信息將包含在JSON屬性"class"中。property參數(shù)設(shè)置為"class",這是包含類型信息的屬性的名稱。

在第二個例子中,use參數(shù)設(shè)置為Id.NAME,這意味著使用邏輯類型名稱作為類型信息。include參數(shù)設(shè)置為As.WRAPPER_OBJECT,這意味著類型信息將作為包裝器包含。@JsonSubTypes注解用于指定實現(xiàn)類,并將它們的邏輯類型名稱與之關(guān)聯(lián)。

JsonSubTypes Annotation

@JsonSubTypes 是一個用于與 @JsonTypeInfo 一起使用的注解,用于指定可序列化的多態(tài)類型的子類型,并將邏輯名稱與 JSON 內(nèi)容中使用的名稱關(guān)聯(lián)起來。

注意,僅注釋屬性或基本類型不會啟用多態(tài)類型處理:此外,需要使用 @JsonTypeInfo 或等效注釋(例如啟用所謂的“默認鍵入”)注釋,并且僅在這種情況下才使用子類型信息。

可用的元素

@JsonSubTypes 注解具有以下元素:

元素類型描述
valueType[]注釋類型的子類型(注釋類或關(guān)聯(lián)到注釋方法的屬性值類型)。這些將被遞歸檢查,以便可以僅通過包含直接子類型來定義類型
@Type注解子類型的定義和可選名稱。如果未定義名稱(空字符串將被忽略),類型的類將被檢查是否有 @JsonTypeName 注解;如果也缺少或為空,則將通過類型 id 機制構(gòu)造默認名稱。默認名稱通?;陬惷?/td>

Type

@Type 是 @JsonSubTypes 中的一個注解,用于聲明子類型。

@Type 注解具有以下元素:

元素類型描述
valueClass<?>子類型的類
nameString類型標識符所使用的邏輯類型名稱,如果定義了,則為空字符串。除非 names 定義為非空。默認情況下使用,如果類沒有 @JsonTypeName 注解的話,會使用默認名稱構(gòu)造類型 id 機制
namesString[](可選)用于類的類型標識符的邏輯類型名稱:如果應(yīng)將多個類型名稱與同一類型關(guān)聯(lián),則使用

使用示例

下面是一個示例,展示了如何使用 @JsonSubTypes 注解:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
    // ...
}

在上面的示例中,Animal 是一個抽象類,它被注釋為可以有子類型。@JsonTypeInfo 注解指定了要使用名稱作為類型標識符,并將類型標識符作為 JSON 屬性的一部分包含在 JSON 中。@JsonSubTypes 注解指定了 DogCat 作為 Animal 的子類型,分別使用名稱 "dog" 和 "cat" 作為它們的類型標識符。

高級用法

解決循環(huán)引用問題

在進行Json序列化時,如果Java對象之間存在循環(huán)引用,就會導(dǎo)致序列化失敗。為了解決這個問題,我們可以使用@JsonIdentityInfo注解來指定對象的標識信息。具體代碼如下:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Employee {
    private int id;
    private String name;
    private Employee manager;
    public Employee(int id, String name, Employee manager) {
        this.id = id;
        this.name = name;
        this.manager = manager;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Employee getManager() {
        return manager;
    }
    public void setManager(Employee manager) {
        this.manager = manager;
    }
}

自定義類型解析器

有時候,我們需要對一些特殊類型的數(shù)據(jù)進行特殊處理,比如將日期字符串轉(zhuǎn)換成Date對象。我們可以使用JsonDeserializer和JsonSerializer來自定義類型的解析和序列化過程。具體代碼如下:

public class DateDeserializer extends JsonDeserializer<Date> {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        String dateStr = jsonParser.getText();
        try {
            return dateFormat.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}
public class DateSerializer extends JsonSerializer<Date> {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(dateFormat.format(date));
    }
}
@JsonDeserialize(using = DateDeserializer.class)
@JsonSerialize(using = DateSerializer.class)
public class Event {
    private String name;
    private Date date;
    public Event(String name, Date date) {
        this.name = name;
        this.date = date;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
}

使用@JsonTypeName自定義類型名稱

有時候,我們希望在Json數(shù)據(jù)中使用自定義的類型名稱,而不是Java類的名稱。可以使用@JsonTypeName注解來實現(xiàn)。具體代碼如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Fish.class, name = "fish")
})
public abstract class Animal {
    ...
}
@JsonTypeName("dog")
public class Dog extends Animal {
    ...
}

性能優(yōu)化

避免重復(fù)解析

在進行Json序列化和反序列化時,我們可能會重復(fù)解析同一個Json數(shù)據(jù)。為了提高性能,我們可以使用ObjectMapper類的readTree()方法將Json數(shù)據(jù)解析成JsonNode對象,并在需要的時候?qū)ζ溥M行操作。具體代碼如下:

JsonNode root = objectMapper.readTree(json);
JsonNode nameNode = root.path("name");
String name = nameNode.asText();

使用緩存機制

在進行Json序列化和反序列化時,我們可以使用緩存機制來提高性能。Jackson庫提供了一個ObjectReader類,它可以緩存Json數(shù)據(jù)的解析結(jié)果,并在下次解析相同的Json數(shù)據(jù)時直接返回緩存結(jié)果,從而避免重復(fù)解析。具體代碼如下:

ObjectReader reader = objectMapper.readerFor(new TypeReference<List<Animal>>() {});
List<Animal> animals = reader.readValue(json);

注意事項與最佳實踐

處理不同版本的數(shù)據(jù)結(jié)構(gòu)

在進行Json序列化和反序列化時,我們需要考慮到數(shù)據(jù)結(jié)構(gòu)的版本變化。如果數(shù)據(jù)結(jié)構(gòu)發(fā)生變化,我們需要進行相應(yīng)的兼容處理,以確保新版本的程序能夠正確地處理舊版本的數(shù)據(jù)。為了處理不同版本的數(shù)據(jù)結(jié)構(gòu),我們可以使用@JsonCreator和@JsonValue注解來自定義對象的構(gòu)造函數(shù)和toString()方法。

使用@JsonSubTypes的局限性

使用@JsonSubTypes注解時,需要注意它的局限性。它只能用于序列化和反序列化Java對象,無法用于處理基本類型和數(shù)組類型。

安全性考慮

在進行Json序列化和反序列化時,我們需要考慮到安全性問題。由于Json數(shù)據(jù)是開放的,存在被惡意篡改和注入的風險。為了防止這種風險,我們可以使用@JsonInclude注解來控制序列化時包含的屬性,以及使用@JsonCreator和@JsonValue注解來限制反序列化的輸入。此外,我們還可以使用JsonNode對象來手動解析Json數(shù)據(jù),以避免使用反序列化機制。

以上就是利用Jackson解決Json序列化和反序列化問題的詳細內(nèi)容,更多關(guān)于Jackson Json序列化與反序列化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java struts2框架簡介

    java struts2框架簡介

    本文主要介紹了java struts2框架的基礎(chǔ)知識。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Mybatis工具類JdbcTypeInterceptor運行時自動添加jdbcType屬性

    Mybatis工具類JdbcTypeInterceptor運行時自動添加jdbcType屬性

    今天小編就為大家分享一篇關(guān)于Mybatis工具類JdbcTypeInterceptor運行時自動添加jdbcType屬性,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • jdk17+springboot使用webservice的踩坑實戰(zhàn)記錄

    jdk17+springboot使用webservice的踩坑實戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于jdk17+springboot使用webservice踩坑的相關(guān)資料,網(wǎng)上很多教程是基于jdk8的,所以很多在17上面跑不起來,折騰兩天,直接給答案,需要的朋友可以參考下
    2024-01-01
  • spring中12種@Transactional的失效場景(小結(jié))

    spring中12種@Transactional的失效場景(小結(jié))

    日常我們進行業(yè)務(wù)開發(fā)時,基本上使用的都是聲明式事務(wù),即為使用@Transactional注解的方式,本文主要介紹了spring中12種@Transactional的失效場景,感興趣的小伙伴們可以參考一下
    2022-01-01
  • spring?項目實現(xiàn)限流方法示例

    spring?項目實現(xiàn)限流方法示例

    這篇文章主要為大家介紹了spring項目實現(xiàn)限流的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Java并發(fā)工具之Exchanger線程間交換數(shù)據(jù)詳解

    Java并發(fā)工具之Exchanger線程間交換數(shù)據(jù)詳解

    這篇文章主要介紹了Java并發(fā)工具之Exchanger線程間交換數(shù)據(jù)詳解,Exchanger是一個用于線程間協(xié)作的工具類,Exchanger用于進行線程間的數(shù)據(jù)交 換,它提供一個同步點,在這個同步點,兩個線程可以交換彼此的數(shù)據(jù),需要的朋友可以參考下
    2023-12-12
  • mybatis 攔截器添加參數(shù)的實現(xiàn)

    mybatis 攔截器添加參數(shù)的實現(xiàn)

    本文主要介紹了MyBatis攔截器中添加參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-12-12
  • 基于Java中UDP的廣播形式(實例講解)

    基于Java中UDP的廣播形式(實例講解)

    下面小編就為大家分享一篇基于Java中UDP的廣播形式(實例講解),具有很好的參考價值,希望對大家有所幫助
    2017-12-12
  • mybatis如何批量更新list對象

    mybatis如何批量更新list對象

    這篇文章主要介紹了mybatis如何批量更新list對象問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 淺談同步監(jiān)視器之同步代碼塊、同步方法

    淺談同步監(jiān)視器之同步代碼塊、同步方法

    下面小編就為大家?guī)硪黄獪\談同步監(jiān)視器之同步代碼塊、同步方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08

最新評論