本篇文章给大家分享的是有关SpringBoot中怎么反序列化子类,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
目标
在SpringBoot接口中,我们一般用@RequestBody类注解需要反序列化的对象,但是当存在多个子类的情况下,常规的反序列化不能满足需求,比如:
我们有一个类Exam用于表示一张试卷:
@Datapublic 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字段都能正确读取,表明反序列化过程中确实是调用了具体子类对应的类来进行实例化的。
以上就是SpringBoot中怎么反序列化子类,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。