我用Java编写了这样的DTO类:
public class AnswersDto {
private String uuid;
private Set<AnswerDto> answers;
}
public class AnswerDto<T> {
private String uuid;
private AnswerType type;
private T value;
}
class LocationAnswerDto extends AnswerDto<Location> {
}
class JobTitleAnswerDto extends AnswerDto<JobTitle> {
}
public enum AnswerType {
LOCATION,
JOB_TITLE,
}
class Location {
String text;
String placeId;
}
class JobTitle {
String id;
String name;
}
在我的项目中,Jackson库用于JSON的序列化和反序列化。
如何配置AnswersDto
(使用特殊注释)或AnswerDto
(注释)类,以便能够在其正文中使用AnswersDto
正确反序列化请求,例如:
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"answers": [
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"type": "LOCATION",
"value": {
"text": "Dublin",
"placeId": "121"
}
},
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"type": "JOB_TITLE",
"value": {
"id": "1",
"name": "Developer"
}
}
]
}
不幸的是,默认情况下,杰克逊将AnswerDto
对象的值映射到LinkedHashMap
而不是正确的(Location
或JobTitle
)类类型的对象。
我应该使用JsonDeserializer<AnswerDto>
和@JsonTypeInfo
编写自定义@JsonSubTypes
或配置吗?
使用
形式的AnswerDto
正确反序列化请求
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"type": "LOCATION",
"value": {
"text": "Dublin",
"placeId": "121"
}
}
我正在使用:
AnswerDto<Location> answerDto = objectMapper.readValue(jsonRequest, new TypeReference<AnswerDto<Location>>() {
});
没有任何其他自定义配置。
答案 0 :(得分:5)
我已使用杰克逊的自定义注释@JsonTypeInfo
和@JsonSubTypes
来解决问题:
public class AnswerDto<T> {
private String uuid;
private AnswerType type;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Location.class, name = AnswerType.Types.LOCATION),
@JsonSubTypes.Type(value = JobTitle.class, name = AnswerType.Types.JOB_TITLE)
})
private T value;
}
答案 1 :(得分:1)
我的建议是为可能的答案值创建一个单独的界面,并在其上使用@JsonTypeInfo
。您也可以从public class Download : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string file = "setup.exe";
if (File.Exists(context.Server.MapPath(file)) && Session["scr"].ToString() == "Ok")
{
context.Response.Clear();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("content-disposition", "attachment;filename=" + Path.GetFileName(file));
context.Response.WriteFile(context.Server.MapPath(file));
context.Response.End();
}
else
{
context.Response.ContentType = "text/plain";
context.Response.Write("File cannot be found!");
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
,type
枚举中删除AnswerDto
字段,然后通过其他AnswerType
类杰克逊为您添加类型信息。喜欢这个
*AnswerDto
结果json将如下所示
public class AnswerDto<T extends AnswerValue> {
private String uuid;
private T value;
}
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY)
interface AnswerValue {}
class Location implements AnswerValue { /*..*/ }
class JobTitle implements AnswerValue { /*..*/ }
将使用
解析{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"answers": [
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"value": {
"@class": "com.demo.Location",
"text": "Dublin",
"placeId": "121"
}
},
{
"uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73",
"value": {
"@class": "com.demo.JobTitle",
"id": "1",
"name": "Developer"
}
}
]
}
但是这个解决方案仅适用于您是json数据生产者的情况,而且您不必考虑向后兼容性。
在其他情况下,您必须为AnswersDto answersDto = objectMapper.readValue(json, AnswersDto.class);
类制作自定义desetializer。