java-如何配置杰克逊以默认类型反序列化命名类型?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java-如何配置杰克逊以默认类型反序列化命名类型?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5492字,纯文字阅读大概需要8分钟。
内容图文
![java-如何配置杰克逊以默认类型反序列化命名类型?](/upload/InfoBanner/zyjiaocheng/683/d4e8841875f64d2db0b6e6f284596f45.jpg)
考虑以下示例:
package com.example;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
public class JacksonDeserializationOfNamedTypes {
public static void main(String[] args) throws Exception {
ObjectMapper jackson = new ObjectMapper();
jackson.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, "@type");
Balloon redBalloon = new Balloon("red");
String json = jackson.writeValueAsString(redBalloon); //{"@type":"Balloon","color":"red"}
//assume the JSON could be anything
Object deserialized = jackson.readValue(json, Object.class);
assert deserialized instanceof Balloon;
assert redBalloon.equals(deserialized);
}
@JsonTypeName("Balloon")
@JsonTypeInfo(use = Id.NAME)
public static final class Balloon {
private final String color;
//for deserialization
private Balloon() {
this.color = null;
}
public Balloon(final String color) {
this.color = color;
}
public String getColor() {
return color;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final Balloon other = (Balloon) obj;
return this.color.equals(other.color);
}
@Override
public int hashCode() {
int result = color.hashCode();
result = 31 * result + color.hashCode();
return result;
}
@Override
public String toString() {
return color + " balloon";
}
}
}
反序列化在运行时失败,但以下情况除外:
线程“主”中的异常java.lang.IllegalArgumentException:无效的类型ID“气球”(对于ID类型“ Id.class”):找不到此类
生成的JSON当然具有Jackson正确确定类型所需的所有信息,因此如何配置ObjectMapper才能将“气球”正确映射到com.example.JacksonDeserializationOfNamedTypes $Balloon?
解决方法:
我当前的解决方案涉及自定义反序列化器和类型名称到Java类型的手动形成的映射的组合:
package com.example.jackson;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class JacksonDeserializerOfNamedTypes extends StdDeserializer<Object> {
private final Map<String, Class<?>> typesByName;
private final String typeProperty;
private JacksonDeserializerOfNamedTypes(final Map<String, Class<?>> typesByName, final String typeProperty) {
super(Object.class);
this.typesByName = typesByName;
this.typeProperty = typeProperty;
}
@Override
public Object deserialize(final JsonParser parser, final DeserializationContext context) throws IOException, JsonProcessingException {
final ObjectCodec codec = parser.getCodec();
final JsonNode root = parser.readValueAsTree();
final JsonNode typeNameNodeOrNull = root.get(typeProperty);
if (typeNameNodeOrNull == null) {
throw new JsonMappingException(parser, "Unable to determine Java type of JSON: " + root);
} else {
final String typeName = typeNameNodeOrNull.asText();
return Optional
.ofNullable(typesByName.get(typeName))
.map(type -> parseOrNull(root, type, codec))
.orElseThrow(() ->
new JsonMappingException(parser, String.format(
"Unsupported type name '%s' in JSON: %s", typeName, root)));
}
}
private <T> T parseOrNull(final JsonNode root, final Class<T> type, final ObjectCodec codec) {
try {
return root.traverse(codec).readValueAs(type);
} catch (IOException e) {
return null;
}
}
public static void main(String[] args) throws Exception {
final Map<String, Class<?>> typesByName = scanForNamedTypes();
final SimpleModule namedTypesModule = new SimpleModule("my-named-types-module");
namedTypesModule.addDeserializer(Object.class, new JacksonDeserializerOfNamedTypes(typesByName, JsonTypeInfo.Id.NAME.getDefaultPropertyName()));
final Car pinto = new Car("Ford", "Pinto", 1971);
final Balloon sharik = new Balloon("blue");
final ObjectMapper mapper = new ObjectMapper().registerModule(namedTypesModule);
System.out.println(mapper.readValue(mapper.writeValueAsString(pinto), Object.class).getClass());
System.out.println(mapper.readValue(mapper.writeValueAsString(sharik), Object.class).getClass());
}
@JsonTypeName("Balloon")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
public static final class Balloon {
public String color;
private Balloon() {}
public Balloon(final String color) {
this.color = color;
}
}
@JsonTypeName("Car")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
public static final class Car {
public String make;
public String model;
public int year;
private Car() {}
public Car(final String make, final String model, final int year) {
this.make = make;
this.model = model;
this.year = year;
}
}
static Map<String, Class<?>> scanForNamedTypes() {
//in reality, i'd be using a framework (e.g. Reflections) to scan the classpath
//for classes tagged with @JsonTypeName to avoid maintaining manual mappings
final Map<String, Class<?>> typesByName = new HashMap<>();
typesByName.put("Balloon", Balloon.class);
typesByName.put("Car", Car.class);
return Collections.unmodifiableMap(typesByName);
}
}
内容总结
以上是互联网集市为您收集整理的java-如何配置杰克逊以默认类型反序列化命名类型?全部内容,希望文章能够帮你解决java-如何配置杰克逊以默认类型反序列化命名类型?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。