偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Spring Boot 優(yōu)雅處理 JSON動(dòng)態(tài)屬性

開(kāi)發(fā) 前端
有時(shí)我們需要處理具有未知屬性的動(dòng)態(tài) JSON 對(duì)象,這些對(duì)象的結(jié)構(gòu)可能在運(yùn)行時(shí)有所不同,超出了預(yù)定義數(shù)據(jù)結(jié)構(gòu)的范圍。在這種情況下,我們就需要采用一些特殊的技術(shù)或策略來(lái)靈活地處理這些動(dòng)態(tài) JSON 對(duì)象。

環(huán)境:SpringBoot3.4.0

1. 簡(jiǎn)介

使用 Jackson 處理預(yù)定義的 JSON 數(shù)據(jù)結(jié)構(gòu)非常簡(jiǎn)單。Spring Boot 默認(rèn)使用 Jackson 作為其 JSON 處理庫(kù),因此,在默認(rèn)情況下,我們無(wú)需進(jìn)行任何額外的配置即可輕松地在 Spring Boot 應(yīng)用中序列化和反序列化 JSON 數(shù)據(jù)。

然而,有時(shí)我們需要處理具有未知屬性的動(dòng)態(tài) JSON 對(duì)象,這些對(duì)象的結(jié)構(gòu)可能在運(yùn)行時(shí)有所不同,超出了預(yù)定義數(shù)據(jù)結(jié)構(gòu)的范圍。在這種情況下,我們就需要采用一些特殊的技術(shù)或策略來(lái)靈活地處理這些動(dòng)態(tài) JSON 對(duì)象。

1.1 什么是動(dòng)態(tài)屬性?

首先,我們有如下的實(shí)體類:

public class Product {
  private String name;
  private String category;
  // getters, setters
}

對(duì)應(yīng)的JSON字符串如下:

{
  "name": "SpringBoot實(shí)戰(zhàn)案例100例",
  "category": "book",
  "details": {
    "price": "70",
    "author": "XGPack"
  }
}

這里的 "details" 代表的是動(dòng)態(tài)屬性,它在 Product 實(shí)體對(duì)象中并沒(méi)有預(yù)先定義的對(duì)應(yīng)屬性。

接下來(lái),本篇文章將介紹4種方式處理這種JSON對(duì)象中包含動(dòng)態(tài)屬性的情況。

2. 實(shí)戰(zhàn)案例

2.1 使用JsonNode屬性

我們可以在 Product 類中添加一個(gè)類型為 com.fasterxml.jackson.databind.JsonNode 的屬性,用來(lái)接收和處理上述的 details 動(dòng)態(tài)屬性,如下示例:

public class Product {


  // other properties
  private JsonNode details;
  // getters, setters
}

測(cè)試代碼

ObjectMapper objectMapper = new ObjectMapper() ;
String json = """
    {
      "name": "SpringBoot實(shí)戰(zhàn)案例100例",
      "category": "book",
      "details": {
        "price": "70",
        "author": "XGPack"
      }
    }
  """ ;
Product product = objectMapper.readValue(json, Product.class) ;
System.err.printf("name: %s, category: %s%n", product.getName(), product.getCategory()) ;
System.out.println("--------------------------------") ;
System.err.printf("price: %s, auther: %s%n", 
  product.getDetails().get("price").asText(),
  product.getDetails().get("author").asText()) ;

輸出結(jié)果

圖片圖片

問(wèn)題得到了解決,但這個(gè)解決方案存在一個(gè)問(wèn)題;由于我們有一個(gè) JsonNode 字段,我們的類依賴于 Jackson 庫(kù)。

2.2 使用Map集合

我們還可以使用Map集合來(lái)接收這些動(dòng)態(tài)屬性,如下示例:

public class Product_Map {
  // other properties
  private Map<String, Object> details;
  // getters, setters
}

測(cè)試代碼

ObjectMapper objectMapper = ... ;
String json = ... ;
Product product = objectMapper.readValue(json, Product.class) ;
System.err.printf("name: %s, category: %s%n", product.getName(), product.getCategory()) ;
System.out.println("--------------------------------") ;
System.err.printf("price: %s, author: %s%n", 
    product.getDetails().get("price"),
    product.getDetails().get("author")) ;

此種方式有通過(guò)JsonNode差不多,只是這種方式不依賴于jackson包。

2.3 使用@JsonAnySetter注解

當(dāng)對(duì)象只包含動(dòng)態(tài)屬性時(shí)(details),上面的2個(gè)解決方案是很好的選擇。然而,有時(shí)我們?cè)谝粋€(gè) JSON 對(duì)象中混合了固定屬性和動(dòng)態(tài)屬性。也就是如下數(shù)據(jù)格式時(shí):

{
  "name": "SpringBoot實(shí)戰(zhàn)案例100例",
  "category": "book",
  "price": "70",
  "author": "XGPack"
}

動(dòng)態(tài)屬性與固定的屬性是平級(jí)混合在一起,這種情況我們可以使用 @JsonAnySetter 注解來(lái)標(biāo)記一個(gè)方法,以處理額外的、未知的屬性。這樣的方法應(yīng)該接受兩個(gè)參數(shù):屬性的key和value。

public class Product {


  // other properties
  private Map<String, Object> details = new LinkedHashMap<>() ;
  @JsonAnySetter
  public void setDetail(String key, Object value) {
      details.put(key, value) ;
  }
  // getters, setters
}

這里,我們?cè)?setter 方法上使用 @JsonAnySetter 注解,以便該方法能夠處理那些動(dòng)態(tài)的屬性。

測(cè)試代碼

ObjectMapper objectMapper = ... ;
String json = ... ;
Product product = objectMapper.readValue(json, Product.class) ;
System.err.printf("name: %s, category: %s%n", product.getName(), product.getCategory()) ;
System.out.println("--------------------------------") ;
System.err.printf("price: %s, author: %s%n", 
    product.getDetails().get("price"),
    product.getDetails().get("author")) ;

輸出結(jié)果

圖片圖片

2.4 自定義反序列化器

在大多數(shù)情況下,這些解決方案都能很好地工作;然而,當(dāng)我們需要更多的控制時(shí),我們可以使用自定義反序列化器來(lái)處理。

public class ProductDeserializer extends StdDeserializer<Product> {
  public ProductDeserializer() {
    this(null);
  }
  public ProductDeserializer(Class<?> vc) {
    super(vc);
  }
  @Override
  public Product_CustomDeserializer deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
    JsonNode node = jp.getCodec().readTree(jp) ;
    // 獲取通用字段
    String name = node.get("name").asText() ;
    String category = node.get("category").asText() ;
    // 獲取動(dòng)態(tài)屬性
    JsonNode detailsNode = node.get("details");
    String price = detailsNode.get("price").asText() ;
    String author = detailsNode.get("author").asText() ;
    Map<String, Object> details = new HashMap<>() ;
    details.put("price", displayAspectRatio) ;
    details.put("author", audioConnector) ;
    return new Product(name, category, details) ;
  }
}

測(cè)試代碼:

ObjectMapper objectMapper = new ObjectMapper() ;
// 注冊(cè)反序列獲器
SimpleModule module = new SimpleModule();
module.addDeserializer(Product.class, new ProductDeserializer());
objectMapper.registerModule(module) ;
String json = ... ;
// ...

這里通過(guò)編程的方式注冊(cè)自定義反序列化器,其它代碼都是一樣的。

我們還可以通過(guò)更簡(jiǎn)單的方式進(jìn)行處理,直接通過(guò)注解的方式注冊(cè)自定義的反序列化器:

@JsonDeserialize(using = ProductDeserializer.class)
public class Product {
  // ...
}

在Spring Boot環(huán)境下,那么還可以通過(guò)如下方式定義和注冊(cè)反序列化器。

@JsonComponent
public class PackJsonComponent {


  // 自定義反序列化
  public static class Deserializer extends JsonDeserializer<Product> {
    @Override
    public Product deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
      JsonNode node = jp.getCodec().readTree(jp) ;
      String name = node.get("name").asText() ;
      String category = node.get("category").asText() ;
      
      // ...
      return new Product(name, category, details) ;
    }
  }
}

使用@JsonComponent注解即可。

責(zé)任編輯:武曉燕 來(lái)源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2021-04-20 10:50:38

Spring Boot代碼Java

2022-10-26 07:14:25

Spring 6Spring業(yè)務(wù)

2024-09-27 12:27:31

2014-07-22 09:01:53

SwiftJSON

2025-03-11 00:55:00

Spring停機(jī)安全

2024-08-02 09:15:22

Spring捕捉格式

2020-03-16 17:20:02

異常處理Spring Boot

2024-12-06 09:27:28

2023-04-17 23:49:09

開(kāi)發(fā)代碼Java

2025-01-13 12:46:31

SpringBootJacksonJSON

2024-10-16 12:23:55

技巧Spring驗(yàn)證

2023-09-13 08:56:51

2022-04-08 16:27:48

SpringBoot異常處理

2021-01-07 14:06:30

Spring BootJUnit5Java

2021-03-09 13:18:53

加密解密參數(shù)

2023-11-01 08:58:10

2024-10-11 11:46:40

2022-06-04 12:25:10

解密加密過(guò)濾器

2022-05-18 12:04:19

Mybatis數(shù)據(jù)源Spring

2024-08-06 11:17:58

SpringJSON數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)