用Jackson进行java.utils.logging.Level类的反序列化将返回null [英] Deserialization of java.utils.logging.Level class with Jackson returns null
问题描述
我正在尝试使用jackson和Lombok Builder反序列化复杂的bean。
我已经解决了许多与其他自定义类型的序列化有关的错误,但是我一直坚持反序列化 Level
对象。序列化可以某种方式工作,但反序列化却不能,如下所示。
I am trying to deserialize a complex bean using jackson and Lombok builder.
I have solved already many errors related to serialization of other custom types but I am stuck with deserializing a Level
object. The serialization works somehow but not the deserialization as shown below.
由于Level类受到保护,因此我无法创建辅助变量以其他方式(例如字符串数组)序列化Level对象的属性,然后调用像我在反序列化 Pair
类型时所做的那样,读取了序列化的辅助变量后,Level的构造函数。
Since the Level class is protected, I cannot for instance create an auxiliary variable to serialize the Level object attributes in a different way (e.g. an array of strings) and then call the constructor of Level after reading the serialized auxiliary variable like I did when deserializing a Pair
type.
Bean I尝试反序列化的过程比下面的要复杂得多,但是我能够在一个更简单易懂的案例研究中重现该问题。
The bean I am trying to deserialize is much more complex than the following, but I was able to reproduce the problem in a simpler more understandable case study.
TL; dr
使用以下命令反序列化java.util.logging.Level杰克逊总是 null
Deserialization of java.util.logging.Level with jackson is always null
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import java.io.IOException;
import java.util.logging.Level;
public class ReproduceSerializationError {
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
MyObj obj1 = MyObj.builder()
.level(Level.FINE)
.var1(10.0)
.build();
System.out.println("initial object = " + obj1.toString());
String serializedOj = serializeObj( obj1, objectMapper );
System.out.println("serialized json = " + serializedOj.toString());
MyObj deserialized = deserializeObj(serializedOj, objectMapper);
System.out.println("deserialized object = " + deserialized.toString());
System.out.println("logging level of deserialized object = " + deserialized.loggingLevel);
}
@ToString
@Getter
@JsonTypeInfo(use= JsonTypeInfo.Id.CLASS, property="class")
@JsonDeserialize(builder = MyObj.MyObjBuilder.class)
private static class MyObj{
private final double var1;
private Level level;
@JsonPOJOBuilder(withPrefix = "")
public static class MyObjBuilder {
}
@Builder
public MyObj(Level level, double var1){
this.level = level;
this.var1 = var1;
}
}
public static String serializeObj(MyObj obj1, ObjectMapper objectMapper) {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj1);
} catch(JsonProcessingException e) {
throw new RuntimeException( e );
}
}
public static MyObj deserializeObj(String jsonInFile, ObjectMapper objectMapper) throws IOException {
return objectMapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).readValue( jsonInFile, MyObj.class);
}
}
上面的代码显示以下内容:
The code above prints the following:
initial object = ReproduceSerializationError.MyObj(var1=10.0, loggingLevel=FINE)
serialized json = {
"class" : "org.targomo.gp2.util.ReproduceSerializationError$MyObj",
"var1" : 10.0,
"loggingLevel" : {
"name" : "FINE",
"resourceBundleName" : "sun.util.logging.resources.logging",
"localizedName" : "FINE"
}
}
deserialized object = ReproduceSerializationError.MyObj(var1=10.0, loggingLevel=null)
logging level of deserialized object = null
如何正确反序列化 MyObj
的 loggingLevel
属性?
How can I correctly deserialize the loggingLevel
attribute of MyObj
?
推荐答案
您需要为 java.util.logging.Level
类实现自定义序列化程序和反序列化程序。由于级别是预定义的,因此我们无法创建它们,因此应使用已创建和声明的实例。参见以下实现:
You need to implement custom serialiser and deserialiser for java.util.logging.Level
class. Since levels are predefined we can not create them, we should use already created and declared instances. See below implementation:
class LevelJsonSerializer extends JsonSerializer<Level> {
@Override
public void serialize(Level value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.getName());
}
}
class LevelJsonDeserializer extends JsonDeserializer<Level> {
@Override
public Level deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String name = p.getText();
return Level.parse(name);
}
}
您可以注册以下课程:
SimpleModule levelModule = new SimpleModule("LevelModule");
levelModule.addSerializer(Level.class, new LevelJsonSerializer());
levelModule.addDeserializer(Level.class, new LevelJsonDeserializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(levelModule);
这篇关于用Jackson进行java.utils.logging.Level类的反序列化将返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!