用Jackson进行java.utils.logging.Level类的反序列化将返回null [英] Deserialization of java.utils.logging.Level class with Jackson returns null

查看:148
本文介绍了用Jackson进行java.utils.logging.Level类的反序列化将返回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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆