溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot實現(xiàn)子類的反序列化示例代碼

發(fā)布時間:2020-10-09 20:45:59 來源:腳本之家 閱讀:157 作者:別拿豆包不當(dāng)干糧 欄目:編程語言

目標

在SpringBoot接口中,我們一般用@RequestBody類注解需要反序列化的對象,但是當(dāng)存在多個子類的情況下,常規(guī)的反序列化不能滿足需求,比如:

我們有一個類Exam用于表示一張試卷:

@Data
public class Exam {

 private String name;
 private List<Question> questions;
}

這里Question比較特殊,Question本身是一個抽象類,提供了一些通用的方法調(diào)用,實際子類有單選題、多選題、判斷題多種情況

SpringBoot實現(xiàn)子類的反序列化示例代碼

實現(xiàn)

SprintBoot內(nèi)置的序列化是使用的Jackson,查閱文檔后發(fā)現(xiàn)Jackson提供了@JsonTypeInfo和@JsonSubTypes這兩個注解,搭配使用,可以根據(jù)指定的字段值來指定實例化中用到的具體的子類類型

這幾個類的實際代碼如下:

抽象基類Question:

@Data
@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.EXISTING_PROPERTY,
  property = "type",
  visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = SingleChoiceQuestion.class, name = Question.SINGLE_CHOICE),
  @JsonSubTypes.Type(value = MultipleChoiceQuestion.class, name = Question.MULTIPLE_CHOICE),
  @JsonSubTypes.Type(value = TrueOrFalseQuestion.class, name = Question.TRUE_OR_FALSE),
})
public abstract class Question {

 protected static final String SINGLE_CHOICE = "single_choice";
 protected static final String MULTIPLE_CHOICE = "multiple_choice";
 protected static final String TRUE_OR_FALSE = "true_or_false";

 protected String type;
 protected String content;
 protected String answer;

 protected boolean isCorrect(String answer) {
  return this.answer.equals(answer);
 }
}

判斷題TrueOrFalseQuestion:

@Data
@EqualsAndHashCode(callSuper = true)
public class TrueOrFalseQuestion extends Question {

  public TrueOrFalseQuestion() {
    this.type = TRUE_OR_FALSE;
  }
}

選擇題ChoiceQuestion:

@Data
@EqualsAndHashCode(callSuper = true)
public abstract class ChoiceQuestion extends Question {

  private List<Option> options;

  @Data
  public static class Option {
    private String code;
    private String content;
  }
}

單選題SingleChoiceQuestion:

@Data
@EqualsAndHashCode(callSuper = true)
public class SingleChoiceQuestion extends ChoiceQuestion {

  public SingleChoiceQuestion() {
    this.type = SINGLE_CHOICE;
  }
}

多選題MultipleChoiceQuestion:

@Data
@EqualsAndHashCode(callSuper = true)
public class MultipleChoiceQuestion extends ChoiceQuestion {

  public MultipleChoiceQuestion() {
    this.type = MULTIPLE_CHOICE;
  }

  @Override
  public void setAnswer(String answer) {
    this.answer = sortString(answer);
  }

  @Override
  public boolean isCorrect(String answer) {
    return this.answer.equals(sortString(answer));
  }

  private String sortString(String str) {
    char[] chars = str.toCharArray();
    Arrays.sort(chars);
    return String.valueOf(chars);
  }
}

測試

接下來測試一下

定義一個接口,我們可以使用@RequestBody傳入一個Exam對象,返回解析結(jié)果:

@RequestMapping(value = "/exam", method = RequestMethod.POST)
public List<String> parseExam(@RequestBody Exam exam) {
  List<String> results = new ArrayList<>();
  results.add(String.format("Parsed an exam, name = %s", exam.getName()));
  results.add(String.format("Exam has %s questions", exam.getQuestions().size())) 
  
  List<String> types = new ArrayList<>();
  for (Question question : exam.getQuestions()) {
    types.add(question.getType());
  }
  results.add(String.format("Questions types: %s", types.toString()));
  return results;
}

項目跑起來,調(diào)用接口測試一下:

curl -X POST \
 http://127.0.0.1:8080/exam/ \
 -H 'Content-Type: application/json' \
 -d '{
  "name":"一場考試",
  "questions": [
    {
      "type": "single_choice",
      "content": "單選題",
      "options": [
        {
          "code":"A",
          "content": "選項A"
        },{
          "code":"B",
          "content": "選項B"
        }],
      "answer": "A"
    },{
      "type": "multiple_choice",
      "content": "多選題",
      "options": [
        {
          "code":"A",
          "content": "選項A"
        },{
          "code":"B",
          "content": "選項B"
        }],
      "answer": "AB"
    },{
      "type": "true_or_false",
      "content": "判斷題",
      "answer": "True"
    }]
}'

接口返回如下:

[
  "Parsed an exam, name = 一場考試",
  "Exam has 3 questions",
  "Questions types: [single_choice, multiple_choice, true_or_false]"
]

這里不同類型的question,type字段都能正確讀取,表明反序列化過程中確實是調(diào)用了具體子類對應(yīng)的類來進行實例化的。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對億速云的支持。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI