成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java 如何序列化不固定的 JSON 字段

開發 前端
起初我以為只能通過 Map 手動解析,但后來發現 Jackson 提供了?@JsonAnyGetter?和?@JsonAnySetter?這兩個注解,專門用來處理這種“動態屬性”。它們能讓我優雅地把未知字段收集起來或者序列化出去,不影響已知字段的正常處理。

最近在處理一個 JSON 接口時,遇到這樣一種情況:返回的數據中包含一些我事先并不知道的字段,這些字段會根據上下文動態變化,沒辦法在 Java 類中提前寫死字段名。

起初我以為只能通過 Map 手動解析,但后來發現 Jackson 提供了 @JsonAnyGetter 和 @JsonAnySetter 這兩個注解,專門用來處理這種“動態屬性”。它們能讓我優雅地把未知字段收集起來或者序列化出去,不影響已知字段的正常處理。

不過我在使用過程中也有點疑惑,比如這兩個注解的用法順序有什么講究?有哪些坑需要避免?這種方式是不是適合所有動態字段的場景?

開家雜貨鋪吧

@JsonAnyGetter/@JsonAnySetter: 像開了一家靈活應對一切需求的「雜貨鋪」????

想象你是個 JSON 雜貨鋪老板,門口寫著招牌:“你有啥,我都能裝;你要啥,我都能配。”

你平時會備一些常規商品(字段),但總有顧客帶些奇怪需求來問:

  • “老板,有沒有草莓味的牙膏?”
  • “能不能加點冰塊到辣醬里?”

這些你事先沒在貨架上準備的“臨時需求”,你也得接單,對吧?

這時候你就需要一對“萬能架子”——也就是:

@JsonAnySetter:隨便放!你給啥我都能接

每次有奇怪字段進來(JSON 反序列化時),你就把它們統統放進一個萬能柜子(通常是 Map<String, Object>):

@JsonAnySetter
public void add(String key, Object value) {
    otherProps.put(key, value);
}

比如這個 JSON:

{
  "name": "豆瓣醬",
  "spicy": true,
  "limited_edition": "yes",
  "extra_notes": "只在冬天賣"
}

你類里只定義了 name 和 spicy 字段,但 limited_edition 和 extra_notes 也能順利進貨,被收納進了 otherProps 這個萬能抽屜里。

@JsonAnySetter 用于標注一個方法,該方法可以接收 JSON 中沒有預定義的屬性。當 Jackson 反序列化 JSON 時,如果遇到未在 Java 類中顯式定義的字段,它會調用這個方法并將字段名和字段值作為參數傳遞給它。

當你在反序列化 JSON 時,不希望顯式定義所有的字段,或者 JSON 中包含了動態的屬性時,使用 @JsonAnySetter 可以自動將這些字段添加到一個 Map 或類似的結構中。

接下來用一個完整的代碼示例,我們來實現反序列化時動態添加屬性:

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

publicclass Person {
    private String name;
    privateint age;

    // 存儲額外的動態屬性
    private Map<String, Object> additionalProperties = new HashMap<>();

    // 添加動態屬性
    @JsonAnySetter
    public void addAdditionalProperty(String key, Object value) {
        this.additionalProperties.put(key, value);
    }

    // 省略 getter 和 setter 方法

    public Map<String, Object> getAdditionalProperties() {
        return additionalProperties;
    }

    public static void main(String[] args) throws Exception {
        String json = "{"name":"John","age":30,"address":"123 Street","nickname":"Johnny"}";

        ObjectMapper mapper = new ObjectMapper();
        Person person = mapper.readValue(json, Person.class);

        System.out.println("Name: " + person.name);  // 輸出:Name: John
        System.out.println("Age: " + person.age);    // 輸出:Age: 30
        System.out.println("Additional Properties: " + person.getAdditionalProperties());
        // 輸出:Additional Properties: {address=123 Street, nickname=Johnny}
    }
}

在這個例子中:

  • Person 類通過 @JsonAnySetter 注解的 addAdditionalProperty 方法來處理動態的屬性。
  • Person 類中沒有顯式的字段來接收 address 和 nickname,但它們被添加到 additionalProperties 中。
  • 當 Jackson 反序列化 JSON 時,它會把 address 和 nickname 作為動態屬性添加到 additionalProperties 中。

輸出:

Name: John
Age: 30
Additional Properties: {address=123 Street, nickname=Johnny}

@JsonAnyGetter:隨便拿!需要啥我都能給

到了序列化的時候,有顧客問你:“老板,這罐醬料里都包含什么成分?”

你就把主料(已有字段)和萬能抽屜里的額外信息一起打包給他,看起來就像全是標準字段一樣輸出!

@JsonAnyGetter
public Map<String, Object> getOtherProps() {
    return otherProps;
}

這樣序列化輸出的 JSON 會自動把 otherProps 里的內容平鋪出去,和其他字段“融為一體”。

@JsonAnyGetter 用于標注一個方法,該方法返回一個 Map 或類似結構,它將包含對象的 動態屬性(即對象中沒有顯式定義的字段)。當 Jackson 序列化對象時,它會將這個 Map 中的鍵值對當作額外的 JSON 屬性來序列化。

當你有一個類,但是它可能會接受動態的字段,或者一些額外的鍵值對時,使用 @JsonAnyGetter 允許你將這些額外的字段序列化為 JSON。

繼續使用上面的person類,它有一些基本的屬性,但你希望允許動態添加額外的屬性,如額外的 "address" 、 "nickname" 等字段。

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

publicclass Person {
    private String name;
    privateint age;

    // 存儲額外的動態屬性
    private Map<String, Object> additionalProperties = new HashMap<>();

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 通過該方法返回所有額外的動態屬性
    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return additionalProperties;
    }

    public void addAdditionalProperty(String key, Object value) {
        this.additionalProperties.put(key, value);
    }

    // 省略 getter 和 setter 方法
}

publicclass Main {
    public static void main(String[] args) throws Exception {
        Person person = new Person("John", 30);
        person.addAdditionalProperty("address", "123 Street");
        person.addAdditionalProperty("nickname", "Johnny");

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(person);
        System.out.println(json);  // 輸出:{"name":"John","age":30,"address":"123 Street","nickname":"Johnny"}
    }
}

在這個例子中:

  • Person 類包含一個 Map<String, Object> 來存儲動態屬性。
  • 使用 @JsonAnyGetter 標注 getAdditionalProperties() 方法,表示 additionalProperties 中的鍵值對應該被序列化為 JSON 字段。
  • 通過調用 addAdditionalProperty() 方法向 additionalProperties 中添加動態字段。

輸出:

{
  "name": "John",
  "age": 30,
  "address": "123 Street",
  "nickname": "Johnny"
}

總結一下!

圖片圖片

特別適合那些字段不固定、可能需要動態擴展的 JSON 數據結構,比如配置項、參數列表、插件信息等。

責任編輯:武曉燕 來源: 一安未來
相關推薦

2025-06-03 01:22:00

JavaJSON字段

2013-03-11 13:55:03

JavaJSON

2009-07-29 13:39:02

JSON序列化和反序列ASP.NET AJA

2018-03-19 10:20:23

Java序列化反序列化

2021-11-18 07:39:41

Json 序列化Vue

2016-10-20 15:54:08

Python數據序列化

2009-06-14 22:01:27

Java對象序列化反序列化

2018-01-17 16:38:07

MSONJSON序列化

2011-06-01 15:05:02

序列化反序列化

2022-08-06 08:41:18

序列化反序列化Hessian

2010-03-19 15:54:21

Java Socket

2010-01-08 11:11:38

JSON 序列化

2024-10-07 08:26:53

2020-12-24 18:46:11

Java序列化編程語言

2024-01-30 13:32:51

JSON反序列化序列化

2011-04-02 09:04:49

Java序列化

2009-08-24 17:14:08

C#序列化

2011-06-01 14:26:11

序列化

2011-03-04 09:25:51

Java序列化

2009-08-06 11:16:25

C#序列化和反序列化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天插天天操 | avav在线看 | 午夜久草| 久久久一二三 | 精品美女视频在免费观看 | 欧美综合精品 | 国产成人黄色 | 日韩成人在线免费观看 | 日韩欧美国产一区二区 | 99在线视频观看 | 亚洲欧美在线视频 | 午夜欧美一区二区三区在线播放 | 蜜月va乱码一区二区三区 | 日本久久久久久 | 三级黄色片在线播放 | 91av入口| www在线视频 | 国产九九九九 | 国产精品欧美一区二区三区 | 一级黄色片日本 | 夫妻午夜影院 | 欧美色综合 | 国产免费让你躁在线视频 | 日日摸夜夜添夜夜添精品视频 | 最近日韩中文字幕 | 国内久久 | 日本在线综合 | 国产99视频精品免费播放照片 | 亚洲毛片在线 | 日韩av在线免费 | 国产精品一区二区av | 99成人免费视频 | 久久99精品久久久久久国产越南 | 一区二区三区高清 | 亚洲一区二区在线视频 | av在线天堂 | 久久一区二区免费视频 | 激情欧美一区二区三区中文字幕 | 成年人网站在线观看视频 | 欧美一级片在线看 | 久久一级 |