SpringBoot实现子类的反序列化示例代码

 更新时间:2019年08月06日 10:51:00   作者:别拿豆包不当干粮  
这篇文章主要给大家介绍了关于SpringBoot实现子类的反序列化的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用SpringBoot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

目标

在SpringBoot接口中,我们一般用@RequestBody类注解需要反序列化的对象,但是当存在多个子类的情况下,常规的反序列化不能满足需求,比如:

我们有一个类Exam用于表示一张试卷:

@Data
public class Exam {

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

这里Question比较特殊,Question本身是一个抽象类,提供了一些通用的方法调用,实际子类有单选题、多选题、判断题多种情况

实现

SprintBoot内置的序列化是使用的Jackson,查阅文档后发现Jackson提供了@JsonTypeInfo和@JsonSubTypes这两个注解,搭配使用,可以根据指定的字段值来指定实例化中用到的具体的子类类型

这几个类的实际代码如下:

抽象基类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对象,返回解析结果:

@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;
}

项目跑起来,调用接口测试一下:

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字段都能正确读取,表明反序列化过程中确实是调用了具体子类对应的类来进行实例化的。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • mybatisplus自动填充属性值的实现步骤

    mybatisplus自动填充属性值的实现步骤

    MyBatis-Plus提供自动填充的功能,帮助自定设置这些字段的值,提升开发效率,本文就来介绍一下如何使用,感兴趣的可以了解一下
    2023-12-12
  • Java调用商品详情API的项目实践

    Java调用商品详情API的项目实践

    在现代电子商务网站中,商品详情API是一个重要的组件,本文就来介绍一下Java调用商品详情API的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Java编程简单应用

    Java编程简单应用

    本文主要介绍了三个简单Java小程序———1、HelloWorld(HelloWorld的来源);2、输出个人信息3、输出特殊图案。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • java实现简单的搜索引擎

    java实现简单的搜索引擎

    这篇文章主要为大家详细介绍了java实现简单的搜索引擎的相关资料,需要的朋友可以参考下
    2016-02-02
  • Spring Boot简介与快速搭建详细步骤

    Spring Boot简介与快速搭建详细步骤

    SpringBoot其本身没有添加什么新的技术,就是整合了一些现有的框架,并提供了一些默认的配置,就是这些默认的配置,极大的提高了我们的开发效率。这篇文章主要介绍了Spring Boot简介与快速搭建,需要的朋友可以参考下
    2021-05-05
  • SpringMVC的处理器适配器-HandlerAdapter的用法及说明

    SpringMVC的处理器适配器-HandlerAdapter的用法及说明

    这篇文章主要介绍了SpringMVC的处理器适配器-HandlerAdapter的用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Springboot项目Maven依赖冲突的问题解决

    Springboot项目Maven依赖冲突的问题解决

    使用Spring Boot和Maven进行项目开发时,依赖冲突是一个常见的问题,本文就来介绍一下Springboot项目Maven依赖冲突的问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-07-07
  • 详解Java如何获取文件编码格式

    详解Java如何获取文件编码格式

    这篇文章主要介绍了详解Java如何获取文件编码格式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Java多线程中的单例模式两种实现方式

    Java多线程中的单例模式两种实现方式

    这篇文章主要介绍了Java多线程中的单例模式两种实现方式的相关资料,需要的朋友可以参考下
    2017-04-04
  • 带你快速搞定java多线程(5)

    带你快速搞定java多线程(5)

    这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下
    2021-07-07

最新评论